7446a43d47e8c842a72b5b4e2e4469184ce4a974
[fio.git] / os / os-mac.h
1 #ifndef FIO_OS_APPLE_H
2 #define FIO_OS_APPLE_H
3
4 #include <errno.h>
5 #include <fcntl.h>
6 #include <sys/disk.h>
7 #include <sys/sysctl.h>
8 #include <sys/time.h>
9 #include <unistd.h>
10 #include <signal.h>
11
12 #include "../file.h"
13
14 #ifndef CLOCK_MONOTONIC
15 #define CLOCK_MONOTONIC 1
16 #endif
17
18 #ifndef CLOCK_REALTIME
19 #define CLOCK_REALTIME 1
20 #endif
21
22 #define FIO_HAVE_POSIXAIO
23 #define FIO_HAVE_CLOCK_MONOTONIC
24 #define FIO_USE_GENERIC_RAND
25
26 #define OS_MAP_ANON             MAP_ANON
27
28 /*
29  * OSX has a pitifully small shared memory segment by default,
30  * so default to a lower number of max jobs supported
31  */
32 #define FIO_MAX_JOBS            128
33
34 typedef off_t off64_t;
35
36 /* OS X as of 10.6 doesn't have the timer_* functions. 
37  * Emulate the functionality using setitimer and sigaction here
38  */
39
40 #define MAX_TIMERS 64
41
42 typedef unsigned int clockid_t;
43 typedef unsigned int timer_t;
44
45 struct itimerspec {
46         struct timespec it_value;
47         struct timespec it_interval;
48 };
49
50 static struct sigevent fio_timers[MAX_TIMERS];
51 static unsigned int num_timers = 0;
52
53 static inline int timer_create(clockid_t clockid, struct sigevent *restrict evp,
54                                  timer_t *restrict timerid)
55 {
56         int current_timer = num_timers;
57         fio_timers[current_timer] = *evp;
58         num_timers++;
59         
60         *timerid = current_timer;
61         return 0;
62 }
63
64 static void sig_alrm(int signum)
65 {
66         union sigval sv;
67         
68         for (int i = 0; i < num_timers; i++) {
69                 if (fio_timers[i].sigev_notify_function == NULL)
70                         continue;
71                 
72                 if (fio_timers[i].sigev_notify == SIGEV_THREAD)
73                         fio_timers[i].sigev_notify_function(sv);
74                 else if (fio_timers[i].sigev_notify == SIGEV_SIGNAL)
75                         kill(getpid(), fio_timers[i].sigev_signo);
76         }
77 }
78
79 static inline int timer_settime(timer_t timerid, int flags,
80                                                                 const struct itimerspec *value, struct itimerspec *ovalue)
81 {
82         struct sigaction sa;
83         struct itimerval tv;
84         struct itimerval tv_out;
85         int rc;
86         
87         tv.it_interval.tv_sec = value->it_interval.tv_sec;
88         tv.it_interval.tv_usec = value->it_interval.tv_nsec / 1000;
89
90         tv.it_value.tv_sec = value->it_value.tv_sec;
91         tv.it_value.tv_usec = value->it_value.tv_nsec / 1000;
92
93         sa.sa_handler = sig_alrm;
94         sigemptyset(&sa.sa_mask);
95         sa.sa_flags = 0;
96         
97         rc = sigaction(SIGALRM, &sa, NULL);
98
99         if (!rc)
100                 rc = setitimer(ITIMER_REAL, &tv, &tv_out);
101         
102         if (!rc && ovalue != NULL) {
103                 ovalue->it_interval.tv_sec = tv_out.it_interval.tv_sec;
104                 ovalue->it_interval.tv_nsec = tv_out.it_interval.tv_usec * 1000;
105                 ovalue->it_value.tv_sec = tv_out.it_value.tv_sec;
106                 ovalue->it_value.tv_nsec = tv_out.it_value.tv_usec * 1000;
107         }
108
109         return rc;
110 }
111
112 static inline int timer_delete(timer_t timer)
113 {
114         return 0;
115 }
116
117 #define FIO_OS_DIRECTIO
118 static inline int fio_set_odirect(int fd)
119 {
120         if (fcntl(fd, F_NOCACHE, 1) == -1)
121                 return errno;
122         return 0;
123 }
124
125 static inline int blockdev_size(struct fio_file *f, unsigned long long *bytes)
126 {
127     uint64_t temp = 1;
128     if (ioctl(f->fd, DKIOCGETBLOCKCOUNT, bytes) == -1)
129                 return errno;
130     if (ioctl(f->fd, DKIOCGETBLOCKSIZE, &temp) == -1)
131                 return errno;
132     (*bytes) *= temp;
133     return 0;
134 }
135
136 static inline int blockdev_invalidate_cache(struct fio_file *f)
137 {
138         return EINVAL;
139 }
140
141 static inline unsigned long long os_phys_mem(void)
142 {
143         int mib[2] = { CTL_HW, HW_PHYSMEM };
144         unsigned long long mem;
145         size_t len = sizeof(mem);
146
147         sysctl(mib, 2, &mem, &len, NULL, 0);
148         return mem;
149 }
150 #endif