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