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)
93 return mono_os_event_wait_multiple (&event, 1, TRUE, timeout);
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)
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]);
134 data = g_new0 (OSEventWaitData, 1);
136 mono_os_event_init (&data->event, FALSE);
139 mono_thread_info_install_interrupt (signal_and_unref, data, &alerted);
141 mono_os_event_destroy (&data->event);
143 return MONO_OS_EVENT_WAIT_RET_ALERTED;
146 if (timeout != MONO_INFINITE_WAIT)
147 start = mono_msec_ticks ();
149 mono_os_cond_init (&signal_cond);
151 mono_os_mutex_lock (&signal_mutex);
153 for (i = 0; i < nevents; ++i)
154 g_ptr_array_add (events [i]->conds, &signal_cond);
156 g_ptr_array_add (data->event.conds, &signal_cond);
165 for (i = 0; i < nevents; ++i) {
166 if (mono_os_event_is_signalled (events [i])) {
173 if (mono_os_event_is_signalled (&data->event))
176 signalled = (count == nevents);
178 signalled = (count > 0);
181 ret = MONO_OS_EVENT_WAIT_RET_SUCCESS_0 + lowest;
185 if (timeout == MONO_INFINITE_WAIT) {
186 mono_os_cond_wait (&signal_cond, &signal_mutex);
191 elapsed = mono_msec_ticks () - start;
192 if (elapsed >= timeout) {
193 ret = MONO_OS_EVENT_WAIT_RET_TIMEOUT;
197 res = mono_os_cond_timedwait (&signal_cond, &signal_mutex, timeout - elapsed);
199 ret = MONO_OS_EVENT_WAIT_RET_TIMEOUT;
206 for (i = 0; i < nevents; ++i)
207 g_ptr_array_remove (events [i]->conds, &signal_cond);
209 g_ptr_array_remove (data->event.conds, &signal_cond);
211 mono_os_mutex_unlock (&signal_mutex);
213 mono_os_cond_destroy (&signal_cond);
215 mono_thread_info_uninstall_interrupt (&alerted);
217 if (InterlockedDecrement ((gint32*) &data->ref) == 0) {
218 mono_os_event_destroy (&data->event);
221 return MONO_OS_EVENT_WAIT_RET_ALERTED;
224 mono_os_event_destroy (&data->event);