[linker] We need to mark nested types even if the declaring type isn't marked.
[mono-project.git] / mono / metadata / threadpool-ms-io-epoll.c
blob2bc99e105b9cca5e57845d28d8ff21e3a68a305d
2 #if defined(HAVE_EPOLL)
4 #include <sys/epoll.h>
6 #if defined(HOST_WIN32)
7 /* We assume that epoll is not available on windows */
8 #error
9 #endif
11 #define EPOLL_NEVENTS 128
13 static gint epoll_fd;
14 static struct epoll_event *epoll_events;
16 static gboolean
17 epoll_init (gint wakeup_pipe_fd)
19 struct epoll_event event;
21 #ifdef EPOOL_CLOEXEC
22 epoll_fd = epoll_create1 (EPOLL_CLOEXEC);
23 #else
24 epoll_fd = epoll_create (256);
25 fcntl (epoll_fd, F_SETFD, FD_CLOEXEC);
26 #endif
28 if (epoll_fd == -1) {
29 #ifdef EPOOL_CLOEXEC
30 g_error ("epoll_init: epoll (EPOLL_CLOEXEC) failed, error (%d) %s\n", errno, g_strerror (errno));
31 #else
32 g_error ("epoll_init: epoll (256) failed, error (%d) %s\n", errno, g_strerror (errno));
33 #endif
34 return FALSE;
37 event.events = EPOLLIN;
38 event.data.fd = wakeup_pipe_fd;
39 if (epoll_ctl (epoll_fd, EPOLL_CTL_ADD, event.data.fd, &event) == -1) {
40 g_error ("epoll_init: epoll_ctl () failed, error (%d) %s", errno, g_strerror (errno));
41 close (epoll_fd);
42 return FALSE;
45 epoll_events = g_new0 (struct epoll_event, EPOLL_NEVENTS);
47 return TRUE;
50 static void
51 epoll_register_fd (gint fd, gint events, gboolean is_new)
53 struct epoll_event event;
55 #ifndef EPOLLONESHOT
56 /* it was only defined on android in May 2013 */
57 #define EPOLLONESHOT 0x40000000
58 #endif
60 event.data.fd = fd;
61 event.events = EPOLLONESHOT;
62 if ((events & EVENT_IN) != 0)
63 event.events |= EPOLLIN;
64 if ((events & EVENT_OUT) != 0)
65 event.events |= EPOLLOUT;
67 if (epoll_ctl (epoll_fd, is_new ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, event.data.fd, &event) == -1)
68 g_error ("epoll_register_fd: epoll_ctl(%s) failed, error (%d) %s", is_new ? "EPOLL_CTL_ADD" : "EPOLL_CTL_MOD", errno, g_strerror (errno));
71 static void
72 epoll_remove_fd (gint fd)
74 if (epoll_ctl (epoll_fd, EPOLL_CTL_DEL, fd, NULL) == -1)
75 g_error ("epoll_remove_fd: epoll_ctl (EPOLL_CTL_DEL) failed, error (%d) %s", errno, g_strerror (errno));
78 static gint
79 epoll_event_wait (void (*callback) (gint fd, gint events, gpointer user_data), gpointer user_data)
81 gint i, ready;
83 memset (epoll_events, 0, sizeof (struct epoll_event) * EPOLL_NEVENTS);
85 mono_gc_set_skip_thread (TRUE);
87 MONO_ENTER_GC_SAFE;
88 ready = epoll_wait (epoll_fd, epoll_events, EPOLL_NEVENTS, -1);
89 MONO_EXIT_GC_SAFE;
91 mono_gc_set_skip_thread (FALSE);
93 if (ready == -1) {
94 switch (errno) {
95 case EINTR:
96 mono_thread_internal_check_for_interruption_critical (mono_thread_internal_current ());
97 ready = 0;
98 break;
99 default:
100 g_error ("epoll_event_wait: epoll_wait () failed, error (%d) %s", errno, g_strerror (errno));
101 break;
105 if (ready == -1)
106 return -1;
108 for (i = 0; i < ready; ++i) {
109 gint fd, events = 0;
111 fd = epoll_events [i].data.fd;
112 if (epoll_events [i].events & (EPOLLIN | EPOLLERR | EPOLLHUP))
113 events |= EVENT_IN;
114 if (epoll_events [i].events & (EPOLLOUT | EPOLLERR | EPOLLHUP))
115 events |= EVENT_OUT;
117 callback (fd, events, user_data);
120 return 0;
123 static ThreadPoolIOBackend backend_epoll = {
124 .init = epoll_init,
125 .register_fd = epoll_register_fd,
126 .remove_fd = epoll_remove_fd,
127 .event_wait = epoll_event_wait,
130 #endif