os-mac.h revision 0209e1e5a24979172596cd1e249b32eaba78969f
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 void sig_alrm(int signum) 73{ 74 union sigval sv; 75 76 for (int i = 0; i < num_timers; i++) { 77 if (fio_timers[i].sigev_notify_function == NULL) 78 continue; 79 80 if (fio_timers[i].sigev_notify == SIGEV_THREAD) 81 fio_timers[i].sigev_notify_function(sv); 82 else if (fio_timers[i].sigev_notify == SIGEV_SIGNAL) 83 kill(getpid(), fio_timers[i].sigev_signo); 84 } 85} 86 87static inline int timer_settime(timer_t timerid, int flags, 88 const struct itimerspec *value, 89 struct itimerspec *ovalue) 90{ 91 struct sigaction sa; 92 struct itimerval tv; 93 struct itimerval tv_out; 94 int rc; 95 96 tv.it_interval.tv_sec = value->it_interval.tv_sec; 97 tv.it_interval.tv_usec = value->it_interval.tv_nsec / 1000; 98 99 tv.it_value.tv_sec = value->it_value.tv_sec; 100 tv.it_value.tv_usec = value->it_value.tv_nsec / 1000; 101 102 sa.sa_handler = sig_alrm; 103 sigemptyset(&sa.sa_mask); 104 sa.sa_flags = 0; 105 106 rc = sigaction(SIGALRM, &sa, NULL); 107 108 if (!rc) 109 rc = setitimer(ITIMER_REAL, &tv, &tv_out); 110 111 if (!rc && ovalue != NULL) { 112 ovalue->it_interval.tv_sec = tv_out.it_interval.tv_sec; 113 ovalue->it_interval.tv_nsec = tv_out.it_interval.tv_usec * 1000; 114 ovalue->it_value.tv_sec = tv_out.it_value.tv_sec; 115 ovalue->it_value.tv_nsec = tv_out.it_value.tv_usec * 1000; 116 } 117 118 return rc; 119} 120 121static inline int timer_delete(timer_t timer) 122{ 123 return 0; 124} 125 126#define FIO_OS_DIRECTIO 127static inline int fio_set_odirect(int fd) 128{ 129 if (fcntl(fd, F_NOCACHE, 1) == -1) 130 return errno; 131 return 0; 132} 133 134static inline int blockdev_size(struct fio_file *f, unsigned long long *bytes) 135{ 136 uint32_t block_size; 137 uint64_t block_count; 138 139 if (ioctl(f->fd, DKIOCGETBLOCKCOUNT, &block_count) == -1) 140 return errno; 141 if (ioctl(f->fd, DKIOCGETBLOCKSIZE, &block_size) == -1) 142 return errno; 143 144 *bytes = block_size; 145 *bytes *= block_count; 146 return 0; 147} 148 149static inline int chardev_size(struct fio_file *f, unsigned long long *bytes) 150{ 151 /* 152 * Could be a raw block device, this is better than just assuming 153 * we can't get the size at all. 154 */ 155 if (!blockdev_size(f, bytes)) 156 return 0; 157 158 *bytes = -1ULL; 159 return 0; 160} 161 162static inline int blockdev_invalidate_cache(struct fio_file *f) 163{ 164 return EINVAL; 165} 166 167static inline unsigned long long os_phys_mem(void) 168{ 169 int mib[2] = { CTL_HW, HW_PHYSMEM }; 170 unsigned long long mem; 171 size_t len = sizeof(mem); 172 173 sysctl(mib, 2, &mem, &len, NULL, 0); 174 return mem; 175} 176 177static inline int gettid(void) 178{ 179 return mach_thread_self(); 180} 181#endif 182