2 * os-event-unix.c: MonoOSEvent on Unix
5 * Ludovic Henry (luhenry@microsoft.com)
7 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
13 #include "mono-lazy-init.h"
14 #include "mono-threads.h"
15 #include "mono-time.h"
17 static mono_lazy_init_t status = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED;
19 static mono_mutex_t signal_mutex;
24 mono_os_mutex_init (&signal_mutex);
28 mono_os_event_init (MonoOSEvent *event, gboolean initial)
32 mono_lazy_initialize (&status, initialize);
34 event->conds = g_ptr_array_new ();
35 event->signalled = initial;
39 mono_os_event_destroy (MonoOSEvent *event)
41 g_assert (mono_lazy_is_initialized (&status));
45 if (event->conds->len > 0)
46 g_error ("%s: cannot destroy osevent, there are still %d threads waiting on it", __func__, event->conds->len);
48 g_ptr_array_free (event->conds, TRUE);
52 mono_os_event_is_signalled (MonoOSEvent *event)
54 return event->signalled;
58 mono_os_event_set (MonoOSEvent *event)
62 g_assert (mono_lazy_is_initialized (&status));
66 mono_os_mutex_lock (&signal_mutex);
68 event->signalled = TRUE;
70 for (i = 0; i < event->conds->len; ++i)
71 mono_os_cond_signal ((mono_cond_t*) event->conds->pdata [i]);
73 mono_os_mutex_unlock (&signal_mutex);
77 mono_os_event_reset (MonoOSEvent *event)
79 g_assert (mono_lazy_is_initialized (&status));
83 mono_os_mutex_lock (&signal_mutex);
85 event->signalled = FALSE;
87 mono_os_mutex_unlock (&signal_mutex);
91 mono_os_event_wait_one (MonoOSEvent *event, guint32 timeout, gboolean alertable)
93 return mono_os_event_wait_multiple (&event, 1, TRUE, timeout, alertable);
102 signal_and_unref (gpointer user_data)
104 OSEventWaitData *data;
106 data = (OSEventWaitData*) user_data;
108 mono_os_event_set (&data->event);
109 if (InterlockedDecrement ((gint32*) &data->ref) == 0) {
110 mono_os_event_destroy (&data->event);
116 mono_os_event_wait_multiple (MonoOSEvent **events, gsize nevents, gboolean waitall, guint32 timeout, gboolean alertable)
118 MonoOSEventWaitRet ret;
119 mono_cond_t signal_cond;
120 OSEventWaitData *data;
125 g_assert (mono_lazy_is_initialized (&status));
128 g_assert (nevents > 0);
129 g_assert (nevents <= MONO_OS_EVENT_WAIT_MAXIMUM_OBJECTS);
131 for (i = 0; i < nevents; ++i)
132 g_assert (events [i]);
135 data = g_new0 (OSEventWaitData, 1);
137 mono_os_event_init (&data->event, FALSE);
140 mono_thread_info_install_interrupt (signal_and_unref, data, &alerted);
142 mono_os_event_destroy (&data->event);
144 return MONO_OS_EVENT_WAIT_RET_ALERTED;
148 if (timeout != MONO_INFINITE_WAIT)
149 start = mono_msec_ticks ();
151 mono_os_cond_init (&signal_cond);
153 mono_os_mutex_lock (&signal_mutex);
155 for (i = 0; i < nevents; ++i)
156 g_ptr_array_add (events [i]->conds, &signal_cond);
159 g_ptr_array_add (data->event.conds, &signal_cond);
168 for (i = 0; i < nevents; ++i) {
169 if (mono_os_event_is_signalled (events [i])) {
176 if (alertable && mono_os_event_is_signalled (&data->event))
179 signalled = (count == nevents);
181 signalled = (count > 0);
184 ret = MONO_OS_EVENT_WAIT_RET_SUCCESS_0 + lowest;
188 if (timeout == MONO_INFINITE_WAIT) {
189 mono_os_cond_wait (&signal_cond, &signal_mutex);
194 elapsed = mono_msec_ticks () - start;
195 if (elapsed >= timeout) {
196 ret = MONO_OS_EVENT_WAIT_RET_TIMEOUT;
200 res = mono_os_cond_timedwait (&signal_cond, &signal_mutex, timeout - elapsed);
202 ret = MONO_OS_EVENT_WAIT_RET_TIMEOUT;
209 for (i = 0; i < nevents; ++i)
210 g_ptr_array_remove (events [i]->conds, &signal_cond);
213 g_ptr_array_remove (data->event.conds, &signal_cond);
215 mono_os_mutex_unlock (&signal_mutex);
217 mono_os_cond_destroy (&signal_cond);
220 mono_thread_info_uninstall_interrupt (&alerted);
222 if (InterlockedDecrement ((gint32*) &data->ref) == 0) {
223 mono_os_event_destroy (&data->event);
226 return MONO_OS_EVENT_WAIT_RET_ALERTED;
229 mono_os_event_destroy (&data->event);