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