[interp] Remove unreachable code (#12411)
[mono-project.git] / mono / utils / os-event-unix.c
blob24b0b1d9a2f543e4e70f620c8429632cb1f8d61c
1 /**
2 * \file
3 * MonoOSEvent on Unix
5 * Author:
6 * Ludovic Henry (luhenry@microsoft.com)
8 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
9 */
11 #include "os-event.h"
13 #include "atomic.h"
14 #include "mono-lazy-init.h"
15 #include "mono-threads.h"
16 #include "mono-time.h"
18 static mono_lazy_init_t status = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED;
20 static mono_mutex_t signal_mutex;
22 static void
23 initialize (void)
25 mono_os_mutex_init (&signal_mutex);
28 void
29 mono_os_event_init (MonoOSEvent *event, gboolean initial)
31 g_assert (event);
33 mono_lazy_initialize (&status, initialize);
35 event->conds = g_ptr_array_new ();
36 event->signalled = initial;
39 void
40 mono_os_event_destroy (MonoOSEvent *event)
42 g_assert (mono_lazy_is_initialized (&status));
44 g_assert (event);
46 if (event->conds->len > 0)
47 g_error ("%s: cannot destroy osevent, there are still %d threads waiting on it", __func__, event->conds->len);
49 g_ptr_array_free (event->conds, TRUE);
52 static gboolean
53 mono_os_event_is_signalled (MonoOSEvent *event)
55 return event->signalled;
58 void
59 mono_os_event_set (MonoOSEvent *event)
61 gsize i;
63 g_assert (mono_lazy_is_initialized (&status));
65 g_assert (event);
67 mono_os_mutex_lock (&signal_mutex);
69 event->signalled = TRUE;
71 for (i = 0; i < event->conds->len; ++i)
72 mono_os_cond_signal ((mono_cond_t*) event->conds->pdata [i]);
74 mono_os_mutex_unlock (&signal_mutex);
77 void
78 mono_os_event_reset (MonoOSEvent *event)
80 g_assert (mono_lazy_is_initialized (&status));
82 g_assert (event);
84 mono_os_mutex_lock (&signal_mutex);
86 event->signalled = FALSE;
88 mono_os_mutex_unlock (&signal_mutex);
91 MonoOSEventWaitRet
92 mono_os_event_wait_one (MonoOSEvent *event, guint32 timeout, gboolean alertable)
94 return mono_os_event_wait_multiple (&event, 1, TRUE, timeout, alertable);
97 typedef struct {
98 guint32 ref;
99 MonoOSEvent event;
100 } OSEventWaitData;
102 static void
103 signal_and_unref (gpointer user_data)
105 OSEventWaitData *data;
107 data = (OSEventWaitData*) user_data;
109 mono_os_event_set (&data->event);
110 if (mono_atomic_dec_i32 ((gint32*) &data->ref) == 0) {
111 mono_os_event_destroy (&data->event);
112 g_free (data);
116 MonoOSEventWaitRet
117 mono_os_event_wait_multiple (MonoOSEvent **events, gsize nevents, gboolean waitall, guint32 timeout, gboolean alertable)
119 MonoOSEventWaitRet ret;
120 mono_cond_t signal_cond;
121 OSEventWaitData *data;
122 gboolean alerted;
123 gint64 start;
124 gint i;
126 g_assert (mono_lazy_is_initialized (&status));
128 g_assert (events);
129 g_assert (nevents > 0);
130 g_assert (nevents <= MONO_OS_EVENT_WAIT_MAXIMUM_OBJECTS);
132 for (i = 0; i < nevents; ++i)
133 g_assert (events [i]);
135 if (alertable) {
136 data = g_new0 (OSEventWaitData, 1);
137 data->ref = 2;
138 mono_os_event_init (&data->event, FALSE);
140 alerted = FALSE;
141 mono_thread_info_install_interrupt (signal_and_unref, data, &alerted);
142 if (alerted) {
143 mono_os_event_destroy (&data->event);
144 g_free (data);
145 return MONO_OS_EVENT_WAIT_RET_ALERTED;
149 if (timeout != MONO_INFINITE_WAIT)
150 start = mono_msec_ticks ();
152 mono_os_cond_init (&signal_cond);
154 mono_os_mutex_lock (&signal_mutex);
156 for (i = 0; i < nevents; ++i)
157 g_ptr_array_add (events [i]->conds, &signal_cond);
159 if (alertable)
160 g_ptr_array_add (data->event.conds, &signal_cond);
162 for (;;) {
163 gint count, lowest;
164 gboolean signalled;
166 count = 0;
167 lowest = -1;
169 for (i = 0; i < nevents; ++i) {
170 if (mono_os_event_is_signalled (events [i])) {
171 count += 1;
172 if (lowest == -1)
173 lowest = i;
177 if (alertable && mono_os_event_is_signalled (&data->event))
178 signalled = TRUE;
179 else if (waitall)
180 signalled = (count == nevents);
181 else /* waitany */
182 signalled = (count > 0);
184 if (signalled) {
185 ret = (MonoOSEventWaitRet)(MONO_OS_EVENT_WAIT_RET_SUCCESS_0 + lowest);
186 goto done;
189 if (timeout == MONO_INFINITE_WAIT) {
190 mono_os_cond_wait (&signal_cond, &signal_mutex);
191 } else {
192 gint64 elapsed;
193 gint res;
195 elapsed = mono_msec_ticks () - start;
196 if (elapsed >= timeout) {
197 ret = MONO_OS_EVENT_WAIT_RET_TIMEOUT;
198 goto done;
201 res = mono_os_cond_timedwait (&signal_cond, &signal_mutex, timeout - elapsed);
202 if (res != 0) {
203 ret = MONO_OS_EVENT_WAIT_RET_TIMEOUT;
204 goto done;
209 done:
210 for (i = 0; i < nevents; ++i)
211 g_ptr_array_remove (events [i]->conds, &signal_cond);
213 if (alertable)
214 g_ptr_array_remove (data->event.conds, &signal_cond);
216 mono_os_mutex_unlock (&signal_mutex);
218 mono_os_cond_destroy (&signal_cond);
220 if (alertable) {
221 mono_thread_info_uninstall_interrupt (&alerted);
222 if (alerted) {
223 if (mono_atomic_dec_i32 ((gint32*) &data->ref) == 0) {
224 mono_os_event_destroy (&data->event);
225 g_free (data);
227 return MONO_OS_EVENT_WAIT_RET_ALERTED;
230 mono_os_event_destroy (&data->event);
231 g_free (data);
234 return ret;