42e1fea98e0bf9e01112f4cf55c5c2d3fab057f8
[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 typedef off_t off64_t;
29
30 /* OS X as of 10.6 doesn't have the timer_* functions. 
31  * Emulate the functionality using setitimer and sigaction here
32  */
33
34 #define MAX_TIMERS 64
35
36 typedef unsigned int clockid_t;
37 typedef unsigned int timer_t;
38
39 struct itimerspec {
40         struct timespec it_value;
41         struct timespec it_interval;
42 };
43
44 static struct sigevent fio_timers[MAX_TIMERS];
45 static unsigned int num_timers = 0;
46
47 static inline int timer_create(clockid_t clockid, struct sigevent *restrict evp,
48                                  timer_t *restrict timerid)
49 {
50         int current_timer = num_timers;
51         fio_timers[current_timer] = *evp;
52         num_timers++;
53         
54         *timerid = current_timer;
55         return 0;
56 }
57
58 static void sig_alrm(int signum)
59 {
60         union sigval sv;
61         
62         for (int i = 0; i < num_timers; i++) {
63                 if (fio_timers[i].sigev_notify_function == NULL)
64                         continue;
65                 
66                 if (fio_timers[i].sigev_notify == SIGEV_THREAD)
67                         fio_timers[i].sigev_notify_function(sv);
68                 else if (fio_timers[i].sigev_notify == SIGEV_SIGNAL)
69                         kill(getpid(), fio_timers[i].sigev_signo);
70         }
71 }
72
73 static inline int timer_settime(timer_t timerid, int flags,
74                                                                 const struct itimerspec *value, struct itimerspec *ovalue)
75 {
76         struct sigaction sa;
77         struct itimerval tv;
78         struct itimerval tv_out;
79         int rc;
80         
81         tv.it_interval.tv_sec = value->it_interval.tv_sec;
82         tv.it_interval.tv_usec = value->it_interval.tv_nsec / 1000;
83
84         tv.it_value.tv_sec = value->it_value.tv_sec;
85         tv.it_value.tv_usec = value->it_value.tv_nsec / 1000;
86
87         sa.sa_handler = sig_alrm;
88         sigemptyset(&sa.sa_mask);
89         sa.sa_flags = 0;
90         
91         rc = sigaction(SIGALRM, &sa, NULL);
92
93         if (!rc)
94                 rc = setitimer(ITIMER_REAL, &tv, &tv_out);
95         
96         if (!rc && ovalue != NULL) {
97                 ovalue->it_interval.tv_sec = tv_out.it_interval.tv_sec;
98                 ovalue->it_interval.tv_nsec = tv_out.it_interval.tv_usec * 1000;
99                 ovalue->it_value.tv_sec = tv_out.it_value.tv_sec;
100                 ovalue->it_value.tv_nsec = tv_out.it_value.tv_usec * 1000;
101         }
102
103         return rc;
104 }
105
106 static inline int timer_delete(timer_t timer)
107 {
108         return 0;
109 }
110
111 #define FIO_OS_DIRECTIO
112 static inline int fio_set_odirect(int fd)
113 {
114         if (fcntl(fd, F_NOCACHE, 1) == -1)
115                 return errno;
116         return 0;
117 }
118
119 static inline int blockdev_size(struct fio_file *f, unsigned long long *bytes)
120 {
121     uint64_t temp = 1;
122     if (ioctl(f->fd, DKIOCGETBLOCKCOUNT, bytes) == -1)
123                 return errno;
124     if (ioctl(f->fd, DKIOCGETBLOCKSIZE, &temp) == -1)
125                 return errno;
126     (*bytes) *= temp;
127     return 0;
128 }
129
130 static inline int blockdev_invalidate_cache(struct fio_file *f)
131 {
132         return EINVAL;
133 }
134
135 static inline unsigned long long os_phys_mem(void)
136 {
137         int mib[2] = { CTL_HW, HW_PHYSMEM };
138         unsigned long long mem;
139         size_t len = sizeof(mem);
140
141         sysctl(mib, 2, &mem, &len, NULL, 0);
142         return mem;
143 }
144 #endif