* Threads which wait for multiple handles wait on this one handle, and when a handle
* is signalled, this handle is signalled too.
*/
-static gpointer _wapi_global_signal_handle;
-
-/* Point to the mutex/cond inside _wapi_global_signal_handle */
-static mono_mutex_t *_wapi_global_signal_mutex;
-static mono_cond_t *_wapi_global_signal_cond;
+static mono_mutex_t _wapi_global_signal_mutex;
+static mono_cond_t _wapi_global_signal_cond;
static void _wapi_handle_unref_full (gpointer handle, gboolean ignore_private_busy_handles);
/* The condition the global signal cond is waiting on is the signalling of
* _any_ handle. So lock it before setting the signalled state.
*/
- thr_ret = mono_os_mutex_lock (_wapi_global_signal_mutex);
+ thr_ret = mono_os_mutex_lock (&_wapi_global_signal_mutex);
if (thr_ret != 0)
g_warning ("Bad call to mono_os_mutex_lock result %d for global signal mutex", thr_ret);
g_assert (thr_ret == 0);
/* Tell everyone blocking on multiple handles that something
* was signalled
*/
- thr_ret = mono_os_cond_broadcast (_wapi_global_signal_cond);
+ thr_ret = mono_os_cond_broadcast (&_wapi_global_signal_cond);
if (thr_ret != 0)
g_warning ("Bad call to mono_os_cond_broadcast result %d for handle %p", thr_ret, handle);
g_assert (thr_ret == 0);
- thr_ret = mono_os_mutex_unlock (_wapi_global_signal_mutex);
+ thr_ret = mono_os_mutex_unlock (&_wapi_global_signal_mutex);
if (thr_ret != 0)
g_warning ("Bad call to mono_os_mutex_unlock result %d for global signal mutex", thr_ret);
g_assert (thr_ret == 0);
g_message ("%s: lock global signal mutex", __func__);
#endif
- return(mono_os_mutex_lock (_wapi_global_signal_mutex));
+ return(mono_os_mutex_lock (&_wapi_global_signal_mutex));
}
int
g_message ("%s: unlock global signal mutex", __func__);
#endif
- return(mono_os_mutex_unlock (_wapi_global_signal_mutex));
+ return(mono_os_mutex_unlock (&_wapi_global_signal_mutex));
}
int
mono_os_mutex_init (&scan_mutex);
- _wapi_global_signal_handle = _wapi_handle_new (WAPI_HANDLE_EVENT, NULL);
-
- _wapi_global_signal_cond = &_WAPI_PRIVATE_HANDLES (GPOINTER_TO_UINT (_wapi_global_signal_handle))->signal_cond;
- _wapi_global_signal_mutex = &_WAPI_PRIVATE_HANDLES (GPOINTER_TO_UINT (_wapi_global_signal_handle))->signal_mutex;
+ mono_os_cond_init (&_wapi_global_signal_cond);
+ mono_os_mutex_init (&_wapi_global_signal_mutex);
}
void
}
}
+static int
+_wapi_handle_timedwait_signal_naked (mono_cond_t *cond, mono_mutex_t *mutex, guint32 timeout, gboolean poll, gboolean *alerted)
+{
+ int res;
+
+ if (!poll) {
+ res = mono_os_cond_timedwait (cond, mutex, timeout);
+ } else {
+ /* This is needed when waiting for process handles */
+ if (!alerted) {
+ /*
+ * pthread_cond_(timed)wait() can return 0 even if the condition was not
+ * signalled. This happens at least on Darwin. We surface this, i.e., we
+ * get spurious wake-ups.
+ *
+ * http://pubs.opengroup.org/onlinepubs/007908775/xsh/pthread_cond_wait.html
+ */
+ res = mono_os_cond_timedwait (cond, mutex, timeout);
+ } else {
+ if (timeout < 100) {
+ /* Real timeout is less than 100ms time */
+ res = mono_os_cond_timedwait (cond, mutex, timeout);
+ } else {
+ res = mono_os_cond_timedwait (cond, mutex, 100);
+
+ /* Mask the fake timeout, this will cause
+ * another poll if the cond was not really signaled
+ */
+ if (res == ETIMEDOUT)
+ res = 0;
+ }
+ }
+ }
+
+ return res;
+}
+
+static void
+signal_global (gpointer unused)
+{
+ /* If we reach here, then interrupt token is set to the flag value, which
+ * means that the target thread is either
+ * - before the first CAS in timedwait, which means it won't enter the wait.
+ * - it is after the first CAS, so it is already waiting, or it will enter
+ * the wait, and it will be interrupted by the broadcast. */
+ mono_os_mutex_lock (&_wapi_global_signal_mutex);
+ mono_os_cond_broadcast (&_wapi_global_signal_cond);
+ mono_os_mutex_unlock (&_wapi_global_signal_mutex);
+}
+
+int
+_wapi_handle_timedwait_signal (guint32 timeout, gboolean poll, gboolean *alerted)
+{
+ int res;
+
+ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: waiting for global", __func__);
+
+ if (alerted)
+ *alerted = FALSE;
+
+ if (alerted) {
+ mono_thread_info_install_interrupt (signal_global, NULL, alerted);
+ if (*alerted)
+ return 0;
+ }
+
+ res = _wapi_handle_timedwait_signal_naked (&_wapi_global_signal_cond, &_wapi_global_signal_mutex, timeout, poll, alerted);
+
+ if (alerted)
+ mono_thread_info_uninstall_interrupt (alerted);
+
+ return res;
+}
+
static void
signal_handle_and_unref (gpointer handle)
{
_wapi_handle_unref (handle);
}
-int
-_wapi_handle_timedwait_signal (guint32 timeout, gboolean poll, gboolean *alerted)
-{
- return _wapi_handle_timedwait_signal_handle (_wapi_global_signal_handle, timeout, poll, alerted);
-}
-
int
_wapi_handle_timedwait_signal_handle (gpointer handle, guint32 timeout, gboolean poll, gboolean *alerted)
{
guint32 idx;
WapiHandleBase *handle_data;
int res;
- mono_cond_t *cond;
- mono_mutex_t *mutex;
MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: waiting for %p (type %s)", __func__, handle,
_wapi_handle_ops_typename (_wapi_handle_type (handle)));
_wapi_handle_ref (handle);
}
- cond = &handle_data->signal_cond;
- mutex = &handle_data->signal_mutex;
-
- if (!poll) {
- res = mono_os_cond_timedwait (cond, mutex, timeout);
- } else {
- /* This is needed when waiting for process handles */
- if (!alerted) {
- /*
- * pthread_cond_(timed)wait() can return 0 even if the condition was not
- * signalled. This happens at least on Darwin. We surface this, i.e., we
- * get spurious wake-ups.
- *
- * http://pubs.opengroup.org/onlinepubs/007908775/xsh/pthread_cond_wait.html
- */
- res = mono_os_cond_timedwait (cond, mutex, timeout);
- } else {
- if (timeout < 100) {
- /* Real timeout is less than 100ms time */
- res = mono_os_cond_timedwait (cond, mutex, timeout);
- } else {
- res = mono_os_cond_timedwait (cond, mutex, 100);
-
- /* Mask the fake timeout, this will cause
- * another poll if the cond was not really signaled
- */
- if (res == ETIMEDOUT)
- res = 0;
- }
- }
- }
+ res = _wapi_handle_timedwait_signal_naked (&handle_data->signal_cond, &handle_data->signal_mutex, timeout, poll, alerted);
if (alerted) {
mono_thread_info_uninstall_interrupt (alerted);