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;
20 static mono_cond_t signal_cond;
25 mono_os_mutex_init (&signal_mutex);
26 mono_os_cond_init (&signal_cond);
30 mono_os_event_init (MonoOSEvent *event, gboolean manual, gboolean initial)
34 mono_lazy_initialize (&status, initialize);
36 mono_os_mutex_init (&event->mutex);
37 mono_os_cond_init (&event->cond);
38 event->signalled = initial;
39 event->manual = manual;
40 event->set_count = (initial && !manual) ? 1 : 0;
44 mono_os_event_destroy (MonoOSEvent *event)
46 g_assert (mono_lazy_is_initialized (&status));
50 mono_os_mutex_destroy (&event->mutex);
51 mono_os_cond_destroy (&event->cond);
55 mono_os_event_signal (MonoOSEvent *event, gboolean broadcast)
59 mono_os_mutex_lock (&signal_mutex);
61 event->signalled = TRUE;
64 mono_os_cond_broadcast (&event->cond);
66 mono_os_cond_signal (&event->cond);
68 mono_os_cond_broadcast (&signal_cond);
70 mono_os_mutex_unlock (&signal_mutex);
74 mono_os_event_set (MonoOSEvent *event)
76 g_assert (mono_lazy_is_initialized (&status));
80 mono_os_mutex_lock (&event->mutex);
83 mono_os_event_signal (event, TRUE);
86 mono_os_event_signal (event, FALSE);
89 mono_os_mutex_unlock (&event->mutex);
93 mono_os_event_reset (MonoOSEvent *event)
95 g_assert (mono_lazy_is_initialized (&status));
99 mono_os_mutex_lock (&event->mutex);
101 if (event->signalled)
102 event->signalled = FALSE;
104 event->set_count = 0;
106 mono_os_mutex_unlock (&event->mutex);
110 mono_os_event_own (MonoOSEvent *event)
114 if (!event->signalled)
117 if (!event->manual) {
118 g_assert (event->set_count > 0);
119 event->set_count -= 1;
121 if (event->set_count == 0)
122 mono_os_event_signal (event, FALSE);
129 mono_os_event_wait_one (MonoOSEvent *event, guint32 timeout)
131 MonoOSEventWaitRet ret;
134 g_assert (mono_lazy_is_initialized (&status));
138 mono_os_mutex_lock (&event->mutex);
140 if (timeout != MONO_INFINITE_WAIT)
141 start = mono_msec_ticks ();
144 if (mono_os_event_own (event)) {
145 ret = MONO_OS_EVENT_WAIT_RET_SUCCESS_0;
149 if (timeout == MONO_INFINITE_WAIT) {
150 mono_os_cond_wait (&event->cond, &event->mutex);
155 elapsed = mono_msec_ticks () - start;
156 if (elapsed >= timeout) {
157 ret = MONO_OS_EVENT_WAIT_RET_TIMEOUT;
161 res = mono_os_cond_timedwait (&event->cond, &event->mutex, timeout - elapsed);
163 ret = MONO_OS_EVENT_WAIT_RET_TIMEOUT;
170 mono_os_mutex_unlock (&event->mutex);
176 mono_os_event_lock_events (MonoOSEvent **events, gsize nevents)
181 for (i = 0; i < nevents; ++i) {
184 res = mono_os_mutex_trylock (&events [i]->mutex);
186 for (j = i - 1; j >= 0; j--)
187 mono_os_mutex_unlock (&events [j]->mutex);
189 mono_thread_info_yield ();
197 mono_os_event_unlock_events (MonoOSEvent **events, gsize nevents)
201 for (i = 0; i < nevents; ++i)
202 mono_os_mutex_unlock (&events [i]->mutex);
206 mono_os_event_wait_multiple (MonoOSEvent **events, gsize nevents, gboolean waitall, guint32 timeout)
208 MonoOSEventWaitRet ret;
212 g_assert (mono_lazy_is_initialized (&status));
215 g_assert (nevents > 0);
216 g_assert (nevents <= MONO_OS_EVENT_WAIT_MAXIMUM_OBJECTS);
219 return mono_os_event_wait_one (events [0], timeout);
221 for (i = 0; i < nevents; ++i) {
222 g_assert (events [i]);
225 if (timeout != MONO_INFINITE_WAIT)
226 start = mono_msec_ticks ();
232 mono_os_event_lock_events (events, nevents);
237 for (i = 0; i < nevents; ++i) {
238 if (events [i]->signalled) {
245 signalled = (waitall && count == nevents) || (!waitall && count > 0);
248 for (i = 0; i < nevents; ++i)
249 mono_os_event_own (events [i]);
252 mono_os_event_unlock_events (events, nevents);
255 ret = MONO_OS_EVENT_WAIT_RET_SUCCESS_0 + lowest;
259 mono_os_mutex_lock (&signal_mutex);
263 for (i = 0; i < nevents; ++i) {
264 if (!events [i]->signalled) {
271 for (i = 0; i < nevents; ++i) {
272 if (events [i]->signalled) {
280 mono_os_mutex_unlock (&signal_mutex);
284 if (timeout == MONO_INFINITE_WAIT) {
285 mono_os_cond_wait (&signal_cond, &signal_mutex);
290 elapsed = mono_msec_ticks () - start;
291 if (elapsed >= timeout) {
292 mono_os_mutex_unlock (&signal_mutex);
294 ret = MONO_OS_EVENT_WAIT_RET_TIMEOUT;
298 res = mono_os_cond_timedwait (&signal_cond, &signal_mutex, timeout - elapsed);
300 mono_os_mutex_unlock (&signal_mutex);
302 ret = MONO_OS_EVENT_WAIT_RET_TIMEOUT;
307 mono_os_mutex_unlock (&signal_mutex);