summaryrefslogtreecommitdiff
path: root/os/os-mac.h
blob: d202e99dd60a93bc3c11dd0088456bbc1a731adf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#ifndef FIO_OS_APPLE_H
#define FIO_OS_APPLE_H

#define	FIO_OS	os_mac

#include <errno.h>
#include <fcntl.h>
#include <sys/disk.h>
#include <sys/sysctl.h>
#include <sys/time.h>
#include <unistd.h>
#include <signal.h>
#include <mach/mach_init.h>
#include <machine/endian.h>
#include <libkern/OSByteOrder.h>

#include "../file.h"

#define FIO_USE_GENERIC_RAND
#define FIO_USE_GENERIC_INIT_RANDOM_STATE
#define FIO_HAVE_GETTID
#define FIO_HAVE_CHARDEV_SIZE

#define OS_MAP_ANON		MAP_ANON

#define fio_swap16(x)	OSSwapInt16(x)
#define fio_swap32(x)	OSSwapInt32(x)
#define fio_swap64(x)	OSSwapInt64(x)

/*
 * OSX has a pitifully small shared memory segment by default,
 * so default to a lower number of max jobs supported
 */
#define FIO_MAX_JOBS		128

typedef off_t off64_t;

/* OS X as of 10.6 doesn't have the timer_* functions. 
 * Emulate the functionality using setitimer and sigaction here
 */

#define MAX_TIMERS 64

typedef unsigned int clockid_t;
typedef unsigned int timer_t;

struct itimerspec {
	struct timespec it_value;
	struct timespec it_interval;
};

static struct sigevent fio_timers[MAX_TIMERS];
static unsigned int num_timers = 0;

static void sig_alrm(int signum)
{
	union sigval sv;
	
	for (int i = 0; i < num_timers; i++) {
		if (fio_timers[i].sigev_notify_function == NULL)
			continue;
		
		if (fio_timers[i].sigev_notify == SIGEV_THREAD)
			fio_timers[i].sigev_notify_function(sv);
		else if (fio_timers[i].sigev_notify == SIGEV_SIGNAL)
			kill(getpid(), fio_timers[i].sigev_signo);
	}
}

static inline int timer_settime(timer_t timerid, int flags,
				const struct itimerspec *value,
				struct itimerspec *ovalue)
{
	struct sigaction sa;
	struct itimerval tv;
	struct itimerval tv_out;
	int rc;
	
	tv.it_interval.tv_sec = value->it_interval.tv_sec;
	tv.it_interval.tv_usec = value->it_interval.tv_nsec / 1000;

	tv.it_value.tv_sec = value->it_value.tv_sec;
	tv.it_value.tv_usec = value->it_value.tv_nsec / 1000;

	sa.sa_handler = sig_alrm;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = 0;
	
	rc = sigaction(SIGALRM, &sa, NULL);

	if (!rc)
		rc = setitimer(ITIMER_REAL, &tv, &tv_out);
	
	if (!rc && ovalue != NULL) {
		ovalue->it_interval.tv_sec = tv_out.it_interval.tv_sec;
		ovalue->it_interval.tv_nsec = tv_out.it_interval.tv_usec * 1000;
		ovalue->it_value.tv_sec = tv_out.it_value.tv_sec;
		ovalue->it_value.tv_nsec = tv_out.it_value.tv_usec * 1000;
	}

	return rc;
}

static inline int timer_delete(timer_t timer)
{
	return 0;
}

#define FIO_OS_DIRECTIO
static inline int fio_set_odirect(int fd)
{
	if (fcntl(fd, F_NOCACHE, 1) == -1)
		return errno;
	return 0;
}

static inline int blockdev_size(struct fio_file *f, unsigned long long *bytes)
{
	uint32_t block_size;
	uint64_t block_count;

	if (ioctl(f->fd, DKIOCGETBLOCKCOUNT, &block_count) == -1)
		return errno;
	if (ioctl(f->fd, DKIOCGETBLOCKSIZE, &block_size) == -1)
		return errno;

	*bytes = block_size;
	*bytes *= block_count;
	return 0;
}

static inline int chardev_size(struct fio_file *f, unsigned long long *bytes)
{
	/*
	 * Could be a raw block device, this is better than just assuming
	 * we can't get the size at all.
	 */
	if (!blockdev_size(f, bytes))
		return 0;

	*bytes = -1ULL;
	return 0;
}

static inline int blockdev_invalidate_cache(struct fio_file *f)
{
	return EINVAL;
}

static inline unsigned long long os_phys_mem(void)
{
	int mib[2] = { CTL_HW, HW_PHYSMEM };
	unsigned long long mem;
	size_t len = sizeof(mem);

	sysctl(mib, 2, &mem, &len, NULL, 0);
	return mem;
}

static inline int gettid(void)
{
	return mach_thread_self();
}

/*
 * For some reason, there's no header definition for fdatasync(), even
 * if it exists.
 */
extern int fdatasync(int fd);

#endif