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 (mono_atomic_dec_i32 ((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
= (MonoOSEventWaitRet
)(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 (mono_atomic_dec_i32 ((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
);