Home | History | Annotate | Download | only in os
      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 #define FIO_USE_GENERIC_RAND
     20 #define FIO_USE_GENERIC_INIT_RANDOM_STATE
     21 #define FIO_HAVE_GETTID
     22 #define FIO_HAVE_CHARDEV_SIZE
     23 
     24 #define OS_MAP_ANON		MAP_ANON
     25 
     26 #define fio_swap16(x)	OSSwapInt16(x)
     27 #define fio_swap32(x)	OSSwapInt32(x)
     28 #define fio_swap64(x)	OSSwapInt64(x)
     29 
     30 /*
     31  * OSX has a pitifully small shared memory segment by default,
     32  * so default to a lower number of max jobs supported
     33  */
     34 #define FIO_MAX_JOBS		128
     35 
     36 typedef off_t off64_t;
     37 
     38 /* OS X as of 10.6 doesn't have the timer_* functions.
     39  * Emulate the functionality using setitimer and sigaction here
     40  */
     41 
     42 #define MAX_TIMERS 64
     43 
     44 typedef unsigned int clockid_t;
     45 typedef unsigned int timer_t;
     46 
     47 struct itimerspec {
     48 	struct timespec it_value;
     49 	struct timespec it_interval;
     50 };
     51 
     52 static struct sigevent fio_timers[MAX_TIMERS];
     53 static unsigned int num_timers = 0;
     54 
     55 static void sig_alrm(int signum)
     56 {
     57 	union sigval sv;
     58 
     59 	for (int i = 0; i < num_timers; i++) {
     60 		if (fio_timers[i].sigev_notify_function == NULL)
     61 			continue;
     62 
     63 		if (fio_timers[i].sigev_notify == SIGEV_THREAD)
     64 			fio_timers[i].sigev_notify_function(sv);
     65 		else if (fio_timers[i].sigev_notify == SIGEV_SIGNAL)
     66 			kill(getpid(), fio_timers[i].sigev_signo);
     67 	}
     68 }
     69 
     70 static inline int timer_settime(timer_t timerid, int flags,
     71 				const struct itimerspec *value,
     72 				struct itimerspec *ovalue)
     73 {
     74 	struct sigaction sa;
     75 	struct itimerval tv;
     76 	struct itimerval tv_out;
     77 	int rc;
     78 
     79 	tv.it_interval.tv_sec = value->it_interval.tv_sec;
     80 	tv.it_interval.tv_usec = value->it_interval.tv_nsec / 1000;
     81 
     82 	tv.it_value.tv_sec = value->it_value.tv_sec;
     83 	tv.it_value.tv_usec = value->it_value.tv_nsec / 1000;
     84 
     85 	sa.sa_handler = sig_alrm;
     86 	sigemptyset(&sa.sa_mask);
     87 	sa.sa_flags = 0;
     88 
     89 	rc = sigaction(SIGALRM, &sa, NULL);
     90 
     91 	if (!rc)
     92 		rc = setitimer(ITIMER_REAL, &tv, &tv_out);
     93 
     94 	if (!rc && ovalue != NULL) {
     95 		ovalue->it_interval.tv_sec = tv_out.it_interval.tv_sec;
     96 		ovalue->it_interval.tv_nsec = tv_out.it_interval.tv_usec * 1000;
     97 		ovalue->it_value.tv_sec = tv_out.it_value.tv_sec;
     98 		ovalue->it_value.tv_nsec = tv_out.it_value.tv_usec * 1000;
     99 	}
    100 
    101 	return rc;
    102 }
    103 
    104 static inline int timer_delete(timer_t timer)
    105 {
    106 	return 0;
    107 }
    108 
    109 #define FIO_OS_DIRECTIO
    110 static inline int fio_set_odirect(int fd)
    111 {
    112 	if (fcntl(fd, F_NOCACHE, 1) == -1)
    113 		return errno;
    114 	return 0;
    115 }
    116 
    117 static inline int blockdev_size(struct fio_file *f, unsigned long long *bytes)
    118 {
    119 	uint32_t block_size;
    120 	uint64_t block_count;
    121 
    122 	if (ioctl(f->fd, DKIOCGETBLOCKCOUNT, &block_count) == -1)
    123 		return errno;
    124 	if (ioctl(f->fd, DKIOCGETBLOCKSIZE, &block_size) == -1)
    125 		return errno;
    126 
    127 	*bytes = block_size;
    128 	*bytes *= block_count;
    129 	return 0;
    130 }
    131 
    132 static inline int chardev_size(struct fio_file *f, unsigned long long *bytes)
    133 {
    134 	/*
    135 	 * Could be a raw block device, this is better than just assuming
    136 	 * we can't get the size at all.
    137 	 */
    138 	if (!blockdev_size(f, bytes))
    139 		return 0;
    140 
    141 	*bytes = -1ULL;
    142 	return 0;
    143 }
    144 
    145 static inline int blockdev_invalidate_cache(struct fio_file *f)
    146 {
    147 	return EINVAL;
    148 }
    149 
    150 static inline unsigned long long os_phys_mem(void)
    151 {
    152 	int mib[2] = { CTL_HW, HW_PHYSMEM };
    153 	unsigned long long mem;
    154 	size_t len = sizeof(mem);
    155 
    156 	sysctl(mib, 2, &mem, &len, NULL, 0);
    157 	return mem;
    158 }
    159 
    160 static inline int gettid(void)
    161 {
    162 	return mach_thread_self();
    163 }
    164 
    165 /*
    166  * For some reason, there's no header definition for fdatasync(), even
    167  * if it exists.
    168  */
    169 extern int fdatasync(int fd);
    170 
    171 #endif
    172