06a7887e7b0bc50248015b76e3b9d554c36f20f9
[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_POLL(func, socket, ...) \
43 struct pollfd pfd = { \
44 .fd = socket, \
45 .events = POLLIN, \
46 }; \
47 if (poll(&pfd, 1, -1) <= 0) \
48 {\
49 return -1; \
50 }\
51 return func(socket, __VA_ARGS__)
52
53 static inline int cancellable_accept(int socket, struct sockaddr *address,
54 socklen_t *address_len)
55 {
56 WRAP_WITH_POLL(accept, socket, address, address_len);
57 }
58 #define accept cancellable_accept
59 static inline int cancellable_recvfrom(int socket, void *buffer, size_t length,
60 int flags, struct sockaddr *address, socklen_t *address_len)
61 {
62 WRAP_WITH_POLL(recvfrom, socket, buffer, length, flags, address, address_len);
63 }
64 #define recvfrom cancellable_recvfrom
65
66 #include <threading/thread.h>
67
68 /*
69 * While select() is a cancellation point, it seems that OS X does not honor
70 * pending cancellation points when entering the function. We manually test for
71 * and honor pending cancellation requests, but this obviously can't prevent
72 * some race conditions where the the cancellation happens after the check,
73 * but before the select.
74 */
75 static inline int precancellable_select(int nfds, fd_set *restrict readfds,
76 fd_set *restrict writefds, fd_set *restrict errorfds,
77 struct timeval *restrict timeout)
78 {
79 if (thread_cancelability(TRUE))
80 {
81 thread_cancellation_point();
82 }
83 else
84 {
85 thread_cancelability(FALSE);
86 }
87 return select(nfds, readfds, writefds, errorfds, timeout);
88 }
89 #define select precancellable_select
90
91 /*
92 * The same as to select(2) applies to poll(2)
93 */
94 static inline int precancellable_poll(struct pollfd fds[], nfds_t nfds,
95 int timeout)
96 {
97 if (thread_cancelability(TRUE))
98 {
99 thread_cancellation_point();
100 }
101 else
102 {
103 thread_cancelability(FALSE);
104 }
105 return poll(fds, nfds, timeout);
106 }
107 #define poll precancellable_poll
108
109 #endif /** APPLE_H_ @}*/