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
);