Home | History | Annotate | Download | only in os
      1 #ifndef FIO_OS_DRAGONFLY_H
      2 #define FIO_OS_DRAGONFLY_H
      3 
      4 #define	FIO_OS	os_dragonfly
      5 
      6 #include <errno.h>
      7 #include <unistd.h>
      8 #include <sys/param.h>
      9 #include <sys/sysctl.h>
     10 #include <sys/statvfs.h>
     11 #include <sys/diskslice.h>
     12 #include <sys/ioctl_compat.h>
     13 #include <sys/usched.h>
     14 #include <sys/resource.h>
     15 
     16 #include "../file.h"
     17 
     18 #define FIO_HAVE_ODIRECT
     19 #define FIO_USE_GENERIC_RAND
     20 #define FIO_USE_GENERIC_INIT_RANDOM_STATE
     21 #define FIO_HAVE_FS_STAT
     22 #define FIO_HAVE_TRIM
     23 #define FIO_HAVE_CHARDEV_SIZE
     24 #define FIO_HAVE_GETTID
     25 #define FIO_HAVE_CPU_AFFINITY
     26 #define FIO_HAVE_IOPRIO
     27 #define FIO_HAVE_SHM_ATTACH_REMOVED
     28 
     29 #define OS_MAP_ANON		MAP_ANON
     30 
     31 #ifndef PTHREAD_STACK_MIN
     32 #define PTHREAD_STACK_MIN 4096
     33 #endif
     34 
     35 #define fio_swap16(x)	bswap16(x)
     36 #define fio_swap32(x)	bswap32(x)
     37 #define fio_swap64(x)	bswap64(x)
     38 
     39 /* This is supposed to equal (sizeof(cpumask_t)*8) */
     40 #define FIO_MAX_CPUS	SMP_MAXCPU
     41 
     42 typedef off_t off64_t;
     43 typedef cpumask_t os_cpu_mask_t;
     44 
     45 /*
     46  * These macros are copied from sys/cpu/x86_64/include/types.h.
     47  * It's okay to copy from arch dependent header because x86_64 is the only
     48  * supported arch, and no other arch is going to be supported any time soon.
     49  *
     50  * These are supposed to be able to be included from userspace by defining
     51  * _KERNEL_STRUCTURES, however this scheme is badly broken that enabling it
     52  * causes compile-time conflicts with other headers. Although the current
     53  * upstream code no longer requires _KERNEL_STRUCTURES, they should be kept
     54  * here for compatibility with older versions.
     55  */
     56 #ifndef CPUMASK_SIMPLE
     57 #define CPUMASK_SIMPLE(cpu)		((uint64_t)1 << (cpu))
     58 #define CPUMASK_TESTBIT(val, i)		((val).ary[((i) >> 6) & 3] & \
     59 					 CPUMASK_SIMPLE((i) & 63))
     60 #define CPUMASK_ORBIT(mask, i)		((mask).ary[((i) >> 6) & 3] |= \
     61 					 CPUMASK_SIMPLE((i) & 63))
     62 #define CPUMASK_NANDBIT(mask, i)	((mask).ary[((i) >> 6) & 3] &= \
     63 					 ~CPUMASK_SIMPLE((i) & 63))
     64 #define CPUMASK_ASSZERO(mask)		do {				\
     65 					(mask).ary[0] = 0;		\
     66 					(mask).ary[1] = 0;		\
     67 					(mask).ary[2] = 0;		\
     68 					(mask).ary[3] = 0;		\
     69 					} while(0)
     70 #endif
     71 
     72 /*
     73  * Define USCHED_GET_CPUMASK as the macro didn't exist until release 4.5.
     74  * usched_set(2) returns EINVAL if the kernel doesn't support it.
     75  *
     76  * Also note usched_set(2) works only for the current thread regardless of
     77  * the command type. It doesn't work against another thread regardless of
     78  * a caller's privilege. A caller would generally specify 0 for pid for the
     79  * current thread though that's the only choice. See BUGS in usched_set(2).
     80  */
     81 #ifndef USCHED_GET_CPUMASK
     82 #define USCHED_GET_CPUMASK	5
     83 #endif
     84 
     85 /* No CPU_COUNT(), but use the default function defined in os/os.h */
     86 #define fio_cpu_count(mask)             CPU_COUNT((mask))
     87 
     88 static inline int fio_cpuset_init(os_cpu_mask_t *mask)
     89 {
     90 	CPUMASK_ASSZERO(*mask);
     91 	return 0;
     92 }
     93 
     94 static inline int fio_cpuset_exit(os_cpu_mask_t *mask)
     95 {
     96 	return 0;
     97 }
     98 
     99 static inline void fio_cpu_clear(os_cpu_mask_t *mask, int cpu)
    100 {
    101 	CPUMASK_NANDBIT(*mask, cpu);
    102 }
    103 
    104 static inline void fio_cpu_set(os_cpu_mask_t *mask, int cpu)
    105 {
    106 	CPUMASK_ORBIT(*mask, cpu);
    107 }
    108 
    109 static inline int fio_cpu_isset(os_cpu_mask_t *mask, int cpu)
    110 {
    111 	if (CPUMASK_TESTBIT(*mask, cpu))
    112 		return 1;
    113 
    114 	return 0;
    115 }
    116 
    117 static inline int fio_setaffinity(int pid, os_cpu_mask_t mask)
    118 {
    119 	int i, firstcall = 1;
    120 
    121 	/* 0 for the current thread, see BUGS in usched_set(2) */
    122 	pid = 0;
    123 
    124 	for (i = 0; i < FIO_MAX_CPUS; i++) {
    125 		if (!CPUMASK_TESTBIT(mask, i))
    126 			continue;
    127 		if (firstcall) {
    128 			if (usched_set(pid, USCHED_SET_CPU, &i, sizeof(int)))
    129 				return -1;
    130 			firstcall = 0;
    131 		} else {
    132 			if (usched_set(pid, USCHED_ADD_CPU, &i, sizeof(int)))
    133 				return -1;
    134 		}
    135 	}
    136 
    137 	return 0;
    138 }
    139 
    140 static inline int fio_getaffinity(int pid, os_cpu_mask_t *mask)
    141 {
    142 	/* 0 for the current thread, see BUGS in usched_set(2) */
    143 	pid = 0;
    144 
    145 	if (usched_set(pid, USCHED_GET_CPUMASK, mask, sizeof(*mask)))
    146 		return -1;
    147 
    148 	return 0;
    149 }
    150 
    151 /* fio code is Linux based, so rename macros to Linux style */
    152 #define IOPRIO_WHO_PROCESS	PRIO_PROCESS
    153 #define IOPRIO_WHO_PGRP		PRIO_PGRP
    154 #define IOPRIO_WHO_USER		PRIO_USER
    155 
    156 #define IOPRIO_MIN_PRIO		1	/* lowest priority */
    157 #define IOPRIO_MAX_PRIO		10	/* highest priority */
    158 
    159 /*
    160  * Prototypes declared in sys/sys/resource.h are preventing from defining
    161  * ioprio_set() with 4 arguments, so define fio's ioprio_set() as a macro.
    162  * Note that there is no idea of class within ioprio_set(2) unlike Linux.
    163  */
    164 #define ioprio_set(which, who, ioprio_class, ioprio)	\
    165 	ioprio_set(which, who, ioprio)
    166 
    167 static inline int blockdev_size(struct fio_file *f, unsigned long long *bytes)
    168 {
    169 	struct partinfo pi;
    170 
    171 	if (!ioctl(f->fd, DIOCGPART, &pi)) {
    172 		*bytes = (unsigned long long) pi.media_size;
    173 		return 0;
    174 	}
    175 
    176 	*bytes = 0;
    177 	return errno;
    178 }
    179 
    180 static inline int chardev_size(struct fio_file *f, unsigned long long *bytes)
    181 {
    182 	return blockdev_size(f, bytes);
    183 }
    184 
    185 static inline int blockdev_invalidate_cache(struct fio_file *f)
    186 {
    187 	return ENOTSUP;
    188 }
    189 
    190 static inline unsigned long long os_phys_mem(void)
    191 {
    192 	int mib[2] = { CTL_HW, HW_PHYSMEM };
    193 	uint64_t mem;
    194 	size_t len = sizeof(mem);
    195 
    196 	sysctl(mib, 2, &mem, &len, NULL, 0);
    197 	return mem;
    198 }
    199 
    200 static inline int gettid(void)
    201 {
    202 	return (int) lwp_gettid();
    203 }
    204 
    205 static inline unsigned long long get_fs_free_size(const char *path)
    206 {
    207 	unsigned long long ret;
    208 	struct statvfs s;
    209 
    210 	if (statvfs(path, &s) < 0)
    211 		return -1ULL;
    212 
    213 	ret = s.f_frsize;
    214 	ret *= (unsigned long long) s.f_bfree;
    215 	return ret;
    216 }
    217 
    218 static inline int os_trim(int fd, unsigned long long start,
    219 			  unsigned long long len)
    220 {
    221 	off_t range[2];
    222 
    223 	range[0] = start;
    224 	range[1] = len;
    225 
    226 	if (!ioctl(fd, IOCTLTRIM, range))
    227 		return 0;
    228 
    229 	return errno;
    230 }
    231 
    232 #ifdef MADV_FREE
    233 #define FIO_MADV_FREE	MADV_FREE
    234 #endif
    235 
    236 static inline int shm_attach_to_open_removed(void)
    237 {
    238 	int x;
    239 	size_t len = sizeof(x);
    240 
    241 	if (sysctlbyname("kern.ipc.shm_allow_removed", &x, &len, NULL, 0) < 0)
    242 		return 0;
    243 
    244 	return x > 0 ? 1 : 0;
    245 }
    246 
    247 #endif
    248