apple: Introduce a central compatibility header with all __APPLE__ quirks
[strongswan.git] / src / libstrongswan / utils / compat / apple.h
1 /*
2 * Copyright (C) 2014 Martin Willi
3 * Copyright (C) 2014 revosec AG
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 /**
17 * @defgroup apple apple
18 * @{ @ingroup compat
19 */
20
21 #ifndef APPLE_H_
22 #define APPLE_H_
23
24 #include <poll.h>
25 #include <sys/socket.h>
26 #include <sys/select.h>
27
28 /* thread_create is a syscall used to create Mach kernel threads and although
29 * there are no errors or warnings during compilation or linkage the dynamic
30 * linker does not use our implementation, therefore we rename it here
31 */
32 #define thread_create(main, arg) strongswan_thread_create(main, arg)
33
34 /* Mach uses a semaphore_create() call, use a different name for ours */
35 #define semaphore_create(x) strongswan_semaphore_create(x)
36
37 /* on Mac OS X 10.5 several system calls we use are no cancellation points.
38 * fortunately, select isn't one of them, so we wrap some of the others with
39 * calls to select(2).
40 */
41
42 #define WRAP_WITH_SELECT(func, socket, ...)\
43 fd_set rfds; FD_ZERO(&rfds); FD_SET(socket, &rfds);\
44 if (select(socket + 1, &rfds, NULL, NULL, NULL) <= 0) { return -1; }\
45 return func(socket, __VA_ARGS__)
46
47 static inline int cancellable_accept(int socket, struct sockaddr *address,
48 socklen_t *address_len)
49 {
50 WRAP_WITH_SELECT(accept, socket, address, address_len);
51 }
52 #define accept cancellable_accept
53 static inline int cancellable_recvfrom(int socket, void *buffer, size_t length,
54 int flags, struct sockaddr *address, socklen_t *address_len)
55 {
56 WRAP_WITH_SELECT(recvfrom, socket, buffer, length, flags, address, address_len);
57 }
58 #define recvfrom cancellable_recvfrom
59
60 #include <threading/thread.h>
61
62 /*
63 * While select() is a cancellation point, it seems that OS X does not honor
64 * pending cancellation points when entering the function. We manually test for
65 * and honor pending cancellation requests, but this obviously can't prevent
66 * some race conditions where the the cancellation happens after the check,
67 * but before the select.
68 */
69 static inline int precancellable_select(int nfds, fd_set *restrict readfds,
70 fd_set *restrict writefds, fd_set *restrict errorfds,
71 struct timeval *restrict timeout)
72 {
73 if (thread_cancelability(TRUE))
74 {
75 thread_cancellation_point();
76 }
77 else
78 {
79 thread_cancelability(FALSE);
80 }
81 return select(nfds, readfds, writefds, errorfds, timeout);
82 }
83 #define select precancellable_select
84
85 /*
86 * The same as to select(2) applies to poll(2)
87 */
88 static inline int precancellable_poll(struct pollfd fds[], nfds_t nfds,
89 int timeout)
90 {
91 if (thread_cancelability(TRUE))
92 {
93 thread_cancellation_point();
94 }
95 else
96 {
97 thread_cancelability(FALSE);
98 }
99 return poll(fds, nfds, timeout);
100 }
101 #define poll precancellable_poll
102
103 #endif /** APPLE_H_ @}*/