os-mac.h revision cca84643cc10cd72b0b453ff92ccb8643ba51493
1#ifndef FIO_OS_APPLE_H 2#define FIO_OS_APPLE_H 3 4#define FIO_OS os_mac 5 6#include <errno.h> 7#include <fcntl.h> 8#include <sys/disk.h> 9#include <sys/sysctl.h> 10#include <sys/time.h> 11#include <unistd.h> 12#include <signal.h> 13#include <mach/mach_init.h> 14#include <machine/endian.h> 15#include <libkern/OSByteOrder.h> 16 17#include "../file.h" 18 19#ifndef CLOCK_MONOTONIC 20#define CLOCK_MONOTONIC 1 21#endif 22 23#ifndef CLOCK_REALTIME 24#define CLOCK_REALTIME 1 25#endif 26 27#define FIO_HAVE_POSIXAIO 28#define FIO_HAVE_CLOCK_MONOTONIC 29#define FIO_USE_GENERIC_RAND 30#define FIO_HAVE_GETTID 31#define FIO_HAVE_CHARDEV_SIZE 32 33#define OS_MAP_ANON MAP_ANON 34 35#if defined(__LITTLE_ENDIAN__) 36#define FIO_LITTLE_ENDIAN 37#elif defined(__BIG_ENDIAN__) 38#define FIO_BIG_ENDIAN 39#else 40#error "Undefined byte order" 41#endif 42 43#define fio_swap16(x) OSSwapInt16(x) 44#define fio_swap32(x) OSSwapInt32(x) 45#define fio_swap64(x) OSSwapInt64(x) 46 47/* 48 * OSX has a pitifully small shared memory segment by default, 49 * so default to a lower number of max jobs supported 50 */ 51#define FIO_MAX_JOBS 128 52 53typedef off_t off64_t; 54 55/* OS X as of 10.6 doesn't have the timer_* functions. 56 * Emulate the functionality using setitimer and sigaction here 57 */ 58 59#define MAX_TIMERS 64 60 61typedef unsigned int clockid_t; 62typedef unsigned int timer_t; 63 64struct itimerspec { 65 struct timespec it_value; 66 struct timespec it_interval; 67}; 68 69static struct sigevent fio_timers[MAX_TIMERS]; 70static unsigned int num_timers = 0; 71 72static inline int timer_create(clockid_t clockid, struct sigevent *restrict evp, 73 timer_t *restrict timerid) 74{ 75 int current_timer = num_timers; 76 fio_timers[current_timer] = *evp; 77 num_timers++; 78 79 *timerid = current_timer; 80 return 0; 81} 82 83static void sig_alrm(int signum) 84{ 85 union sigval sv; 86 87 for (int i = 0; i < num_timers; i++) { 88 if (fio_timers[i].sigev_notify_function == NULL) 89 continue; 90 91 if (fio_timers[i].sigev_notify == SIGEV_THREAD) 92 fio_timers[i].sigev_notify_function(sv); 93 else if (fio_timers[i].sigev_notify == SIGEV_SIGNAL) 94 kill(getpid(), fio_timers[i].sigev_signo); 95 } 96} 97 98static inline int timer_settime(timer_t timerid, int flags, 99 const struct itimerspec *value, struct itimerspec *ovalue) 100{ 101 struct sigaction sa; 102 struct itimerval tv; 103 struct itimerval tv_out; 104 int rc; 105 106 tv.it_interval.tv_sec = value->it_interval.tv_sec; 107 tv.it_interval.tv_usec = value->it_interval.tv_nsec / 1000; 108 109 tv.it_value.tv_sec = value->it_value.tv_sec; 110 tv.it_value.tv_usec = value->it_value.tv_nsec / 1000; 111 112 sa.sa_handler = sig_alrm; 113 sigemptyset(&sa.sa_mask); 114 sa.sa_flags = 0; 115 116 rc = sigaction(SIGALRM, &sa, NULL); 117 118 if (!rc) 119 rc = setitimer(ITIMER_REAL, &tv, &tv_out); 120 121 if (!rc && ovalue != NULL) { 122 ovalue->it_interval.tv_sec = tv_out.it_interval.tv_sec; 123 ovalue->it_interval.tv_nsec = tv_out.it_interval.tv_usec * 1000; 124 ovalue->it_value.tv_sec = tv_out.it_value.tv_sec; 125 ovalue->it_value.tv_nsec = tv_out.it_value.tv_usec * 1000; 126 } 127 128 return rc; 129} 130 131static inline int timer_delete(timer_t timer) 132{ 133 return 0; 134} 135 136#define FIO_OS_DIRECTIO 137static inline int fio_set_odirect(int fd) 138{ 139 if (fcntl(fd, F_NOCACHE, 1) == -1) 140 return errno; 141 return 0; 142} 143 144static inline int blockdev_size(struct fio_file *f, unsigned long long *bytes) 145{ 146 uint64_t temp = 1; 147 if (ioctl(f->fd, DKIOCGETBLOCKCOUNT, bytes) == -1) 148 return errno; 149 if (ioctl(f->fd, DKIOCGETBLOCKSIZE, &temp) == -1) 150 return errno; 151 (*bytes) *= temp; 152 return 0; 153} 154 155static inline int chardev_size(struct fio_file *f, unsigned long long *bytes) 156{ 157 /* 158 * Could be a raw block device, this is better than just assuming 159 * we can't get the size at all. 160 */ 161 if (!blockdev_size(f, bytes)) 162 return 0; 163 164 *bytes = -1ULL; 165 return 0; 166} 167 168static inline int blockdev_invalidate_cache(struct fio_file *f) 169{ 170 return EINVAL; 171} 172 173static inline unsigned long long os_phys_mem(void) 174{ 175 int mib[2] = { CTL_HW, HW_PHYSMEM }; 176 unsigned long long mem; 177 size_t len = sizeof(mem); 178 179 sysctl(mib, 2, &mem, &len, NULL, 0); 180 return mem; 181} 182 183static inline int gettid(void) 184{ 185 return mach_thread_self(); 186} 187#endif 188