1 /*
2 * ivykis, an event handling library
3 * Copyright (C) 2010, 2012 Lennert Buytenhek
4 * Dedicated to Marija Kulikova.
5 *
6 * This library is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License version
8 * 2.1 as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License version 2.1 for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License version 2.1 along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21 #include "config.h"
22 #include <errno.h>
23 #ifdef HAVE_SYS_EVENTFD_H
24 #include <sys/eventfd.h>
25 #endif
26 #include <sys/syscall.h>
27 #include <unistd.h>
28
29 #ifdef __i386__
30 #ifndef __NR_eventfd
31 #define __NR_eventfd 323
32 #endif
33 #ifndef __NR_eventfd2
34 #define __NR_eventfd2 328
35 #endif
36 #endif
37
38 #ifdef __x86_64__
39 #ifndef __NR_eventfd
40 #define __NR_eventfd 284
41 #endif
42 #ifndef __NR_eventfd2
43 #define __NR_eventfd2 290
44 #endif
45 #endif
46
47 #if defined(__i386__) || defined(__x86_64__)
48 #ifndef EFD_CLOEXEC
49 #define EFD_CLOEXEC 02000000
50 #endif
51 #ifndef EFD_NONBLOCK
52 #define EFD_NONBLOCK 04000
53 #endif
54 #endif
55
56 static int eventfd_in_use = 2;
57
eventfd_grab(void)58 static int eventfd_grab(void)
59 {
60 #if (defined(__NR_eventfd2) || defined(HAVE_EVENTFD)) && \
61 defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK)
62 if (eventfd_in_use == 2) {
63 int ret;
64
65 #ifdef __NR_eventfd2
66 ret = syscall(__NR_eventfd2, 0, EFD_CLOEXEC | EFD_NONBLOCK);
67 #else
68 ret = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
69 #endif
70 if (ret >= 0)
71 return ret;
72
73 if (errno != EINVAL && errno != ENOSYS)
74 return -errno;
75
76 eventfd_in_use = 1;
77 }
78 #endif
79
80 #if defined(__NR_eventfd) || defined(HAVE_EVENTFD)
81 if (eventfd_in_use) {
82 int ret;
83
84 #ifdef __NR_eventfd
85 ret = syscall(__NR_eventfd, 0);
86 #else
87 ret = eventfd(0, 0);
88 #endif
89 if (ret >= 0)
90 return ret;
91
92 if (errno != ENOSYS)
93 return -errno;
94 }
95 #endif
96
97 eventfd_in_use = 0;
98
99 return -ENOSYS;
100 }
101