[mono-api-html] Add filter for new namespaces/types
[mono-project.git] / mono / metadata / tpool-epoll.c
blobbab57abf876b973ceb9ded37fb05289e927be4fe
1 /*
2 * tpool-epoll.c: epoll related stuff
4 * Authors:
5 * Dietmar Maurer (dietmar@ximian.com)
6 * Gonzalo Paniagua Javier (gonzalo@ximian.com)
8 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
9 * Copyright 2004-2011 Novell, Inc (http://www.novell.com)
10 * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
13 struct _tp_epoll_data {
14 int epollfd;
17 typedef struct _tp_epoll_data tp_epoll_data;
18 static void tp_epoll_modify (gpointer p, int fd, int operation, int events, gboolean is_new);
19 static void tp_epoll_shutdown (gpointer event_data);
20 static void tp_epoll_wait (gpointer event_data);
22 static gpointer
23 tp_epoll_init (SocketIOData *data)
25 tp_epoll_data *result;
27 result = g_new0 (tp_epoll_data, 1);
28 #ifdef EPOLL_CLOEXEC
29 result->epollfd = epoll_create1 (EPOLL_CLOEXEC);
30 #else
31 result->epollfd = epoll_create (256); /* The number does not really matter */
32 fcntl (result->epollfd, F_SETFD, FD_CLOEXEC);
33 #endif
34 if (result->epollfd == -1) {
35 int err = errno;
36 if (g_getenv ("MONO_DEBUG")) {
37 #ifdef EPOLL_CLOEXEC
38 g_message ("epoll_create1(EPOLL_CLOEXEC) failed: %d %s", err, g_strerror (err));
39 #else
40 g_message ("epoll_create(256) failed: %d %s", err, g_strerror (err));
41 #endif
44 return NULL;
47 data->shutdown = tp_epoll_shutdown;
48 data->modify = tp_epoll_modify;
49 data->wait = tp_epoll_wait;
50 return result;
53 static void
54 tp_epoll_modify (gpointer p, int fd, int operation, int events, gboolean is_new)
56 SocketIOData *socket_io_data;
57 tp_epoll_data *data;
58 struct epoll_event evt;
59 int epoll_op;
61 socket_io_data = p;
62 data = socket_io_data->event_data;
64 memset (&evt, 0, sizeof (evt));
65 evt.data.fd = fd;
66 if ((events & MONO_POLLIN) != 0)
67 evt.events |= EPOLLIN;
68 if ((events & MONO_POLLOUT) != 0)
69 evt.events |= EPOLLOUT;
71 epoll_op = (is_new) ? EPOLL_CTL_ADD : EPOLL_CTL_MOD;
72 if (epoll_ctl (data->epollfd, epoll_op, fd, &evt) == -1) {
73 int err = errno;
74 if (epoll_op == EPOLL_CTL_ADD && err == EEXIST) {
75 epoll_op = EPOLL_CTL_MOD;
76 if (epoll_ctl (data->epollfd, epoll_op, fd, &evt) == -1) {
77 g_message ("epoll_ctl(MOD): %d %s", err, g_strerror (err));
81 mono_mutex_unlock (&socket_io_data->io_lock);
84 static void
85 tp_epoll_shutdown (gpointer event_data)
87 tp_epoll_data *data = event_data;
89 close (data->epollfd);
90 g_free (data);
93 #define EPOLL_ERRORS (EPOLLERR | EPOLLHUP)
94 #define EPOLL_NEVENTS 128
95 static void
96 tp_epoll_wait (gpointer p)
98 SocketIOData *socket_io_data;
99 int epollfd;
100 struct epoll_event *events, *evt;
101 int ready = 0, i;
102 gpointer async_results [EPOLL_NEVENTS * 2]; // * 2 because each loop can add up to 2 results here
103 gint nresults;
104 tp_epoll_data *data;
106 socket_io_data = p;
107 data = socket_io_data->event_data;
108 epollfd = data->epollfd;
109 events = g_new0 (struct epoll_event, EPOLL_NEVENTS);
111 while (1) {
112 mono_gc_set_skip_thread (TRUE);
114 do {
115 if (ready == -1) {
116 check_for_interruption_critical ();
118 ready = epoll_wait (epollfd, events, EPOLL_NEVENTS, -1);
119 } while (ready == -1 && errno == EINTR);
121 mono_gc_set_skip_thread (FALSE);
123 if (ready == -1) {
124 int err = errno;
125 g_free (events);
126 if (err != EBADF)
127 g_warning ("epoll_wait: %d %s", err, g_strerror (err));
129 return;
132 mono_mutex_lock (&socket_io_data->io_lock);
133 if (socket_io_data->inited == 3) {
134 g_free (events);
135 mono_mutex_unlock (&socket_io_data->io_lock);
136 return; /* cleanup called */
139 nresults = 0;
140 for (i = 0; i < ready; i++) {
141 int fd;
142 MonoMList *list;
143 MonoObject *ares;
145 evt = &events [i];
146 fd = evt->data.fd;
147 list = mono_g_hash_table_lookup (socket_io_data->sock_to_state, GINT_TO_POINTER (fd));
148 if (list != NULL && (evt->events & (EPOLLIN | EPOLL_ERRORS)) != 0) {
149 ares = get_io_event (&list, MONO_POLLIN);
150 if (ares != NULL)
151 async_results [nresults++] = ares;
154 if (list != NULL && (evt->events & (EPOLLOUT | EPOLL_ERRORS)) != 0) {
155 ares = get_io_event (&list, MONO_POLLOUT);
156 if (ares != NULL)
157 async_results [nresults++] = ares;
160 if (list != NULL) {
161 int p;
163 mono_g_hash_table_replace (socket_io_data->sock_to_state, GINT_TO_POINTER (fd), list);
164 p = get_events_from_list (list);
165 evt->events = (p & MONO_POLLOUT) ? EPOLLOUT : 0;
166 evt->events |= (p & MONO_POLLIN) ? EPOLLIN : 0;
167 if (epoll_ctl (epollfd, EPOLL_CTL_MOD, fd, evt) == -1) {
168 if (epoll_ctl (epollfd, EPOLL_CTL_ADD, fd, evt) == -1) {
169 int err = errno;
170 g_message ("epoll(ADD): %d %s", err, g_strerror (err));
173 } else {
174 mono_g_hash_table_remove (socket_io_data->sock_to_state, GINT_TO_POINTER (fd));
175 epoll_ctl (epollfd, EPOLL_CTL_DEL, fd, evt);
178 mono_mutex_unlock (&socket_io_data->io_lock);
179 threadpool_append_jobs (&async_io_tp, (MonoObject **) async_results, nresults);
180 mono_gc_bzero_aligned (async_results, sizeof (gpointer) * nresults);
183 #undef EPOLL_NEVENTS
184 #undef EPOLL_ERRORS