6 * Ludovic Henry (luhenry@microsoft.com)
8 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
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;
25 mono_os_mutex_init (&signal_mutex);
29 mono_os_event_init (MonoOSEvent *event, gboolean initial)
33 mono_lazy_initialize (&status, initialize);
35 event->conds = g_ptr_array_new ();
36 event->signalled = initial;
40 mono_os_event_destroy (MonoOSEvent *event)
42 g_assert (mono_lazy_is_initialized (&status));
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);
53 mono_os_event_is_signalled (MonoOSEvent *event)
55 return event->signalled;
59 mono_os_event_set (MonoOSEvent *event)
63 g_assert (mono_lazy_is_initialized (&status));
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);
78 mono_os_event_reset (MonoOSEvent *event)
80 g_assert (mono_lazy_is_initialized (&status));
84 mono_os_mutex_lock (&signal_mutex);
86 event->signalled = FALSE;
88 mono_os_mutex_unlock (&signal_mutex);
92 mono_os_event_wait_one (MonoOSEvent *event, guint32 timeout, gboolean alertable)
94 return mono_os_event_wait_multiple (&event, 1, TRUE, timeout, alertable);
103 signal_and_unref (gpointer user_data)
105 OSEventWaitData *data;
107 data = (OSEventWaitData*) user_data;
109 mono_os_event_set (&data->event);
110 if (InterlockedDecrement ((gint32*) &data->ref) == 0) {
111 mono_os_event_destroy (&data->event);
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;
126 g_assert (mono_lazy_is_initialized (&status));
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]);
136 data = g_new0 (OSEventWaitData, 1);
138 mono_os_event_init (&data->event, FALSE);
141 mono_thread_info_install_interrupt (signal_and_unref, data, &alerted);
143 mono_os_event_destroy (&data->event);
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);
160 g_ptr_array_add (data->event.conds, &signal_cond);
169 for (i = 0; i < nevents; ++i) {
170 if (mono_os_event_is_signalled (events [i])) {
177 if (alertable && mono_os_event_is_signalled (&data->event))
180 signalled = (count == nevents);
182 signalled = (count > 0);
185 ret = MONO_OS_EVENT_WAIT_RET_SUCCESS_0 + lowest;
189 if (timeout == MONO_INFINITE_WAIT) {
190 mono_os_cond_wait (&signal_cond, &signal_mutex);
195 elapsed = mono_msec_ticks () - start;
196 if (elapsed >= timeout) {
197 ret = MONO_OS_EVENT_WAIT_RET_TIMEOUT;
201 res = mono_os_cond_timedwait (&signal_cond, &signal_mutex, timeout - elapsed);
203 ret = MONO_OS_EVENT_WAIT_RET_TIMEOUT;
210 for (i = 0; i < nevents; ++i)
211 g_ptr_array_remove (events [i]->conds, &signal_cond);
214 g_ptr_array_remove (data->event.conds, &signal_cond);
216 mono_os_mutex_unlock (&signal_mutex);
218 mono_os_cond_destroy (&signal_cond);
221 mono_thread_info_uninstall_interrupt (&alerted);
223 if (InterlockedDecrement ((gint32*) &data->ref) == 0) {
224 mono_os_event_destroy (&data->event);
227 return MONO_OS_EVENT_WAIT_RET_ALERTED;
230 mono_os_event_destroy (&data->event);