[gc] Replace domain finalizer request cond+mutex by a semaphore
authorLudovic Henry <ludovic@xamarin.com>
Fri, 29 Jul 2016 22:40:13 +0000 (00:40 +0200)
committerLudovic Henry <ludovic@xamarin.com>
Sat, 30 Jul 2016 09:58:41 +0000 (11:58 +0200)
This is possible because we only wait for it at one place, and only post it at one other place.

mono/metadata/gc.c

index 9bf14558becd5f69feebb879393fcb6cb411b37b..d77bc2cf82faeb69ad925a5ea17221d9ff9f3005 100644 (file)
 
 typedef struct DomainFinalizationReq {
        MonoDomain *domain;
-#ifdef TARGET_WIN32
-       HANDLE done_event;
-#else
-       gboolean done;
-       MonoCoopCond cond;
-       MonoCoopMutex mutex;
-#endif
+       MonoCoopSem done;
 } DomainFinalizationReq;
 
 static gboolean gc_disabled = FALSE;
@@ -100,51 +94,6 @@ guarded_wait (HANDLE handle, guint32 timeout, gboolean alertable)
        return result;
 }
 
-typedef struct {
-       MonoCoopCond *cond;
-       MonoCoopMutex *mutex;
-} BreakCoopAlertableWaitUD;
-
-static inline void
-break_coop_alertable_wait (gpointer user_data)
-{
-       BreakCoopAlertableWaitUD *ud = (BreakCoopAlertableWaitUD*)user_data;
-
-       mono_coop_mutex_lock (ud->mutex);
-       mono_coop_cond_signal (ud->cond);
-       mono_coop_mutex_unlock (ud->mutex);
-}
-
-/*
- * coop_cond_timedwait_alertable:
- *
- *   Wait on COND/MUTEX. If ALERTABLE is non-null, the wait can be interrupted.
- * In that case, *ALERTABLE will be set to TRUE, and 0 is returned.
- */
-static inline gint
-coop_cond_timedwait_alertable (MonoCoopCond *cond, MonoCoopMutex *mutex, guint32 timeout_ms, gboolean *alertable)
-{
-       int res;
-
-       if (alertable) {
-               BreakCoopAlertableWaitUD ud;
-
-               *alertable = FALSE;
-               ud.cond = cond;
-               ud.mutex = mutex;
-               mono_thread_info_install_interrupt (break_coop_alertable_wait, &ud, alertable);
-               if (*alertable)
-                       return 0;
-       }
-       res = mono_coop_cond_timedwait (cond, mutex, timeout_ms);
-       if (alertable) {
-               mono_thread_info_uninstall_interrupt (alertable);
-               if (*alertable)
-                       return 0;
-       }
-       return res;
-}
-
 static gboolean
 add_thread_to_finalize (MonoInternalThread *thread, MonoError *error)
 {
@@ -459,17 +408,7 @@ mono_domain_finalize (MonoDomain *domain, guint32 timeout)
 
        req = g_new0 (DomainFinalizationReq, 1);
        req->domain = domain;
-
-#ifdef TARGET_WIN32
-       req->done_event = CreateEvent (NULL, TRUE, FALSE, NULL);
-       if (req->done_event == NULL) {
-               g_free (req);
-               return FALSE;
-       }
-#else
-       mono_coop_cond_init (&req->cond);
-       mono_coop_mutex_init (&req->mutex);
-#endif
+       mono_coop_sem_init (&req->done, 0);
 
        if (domain == mono_get_root_domain ())
                finalizing_root_domain = TRUE;
@@ -486,48 +425,23 @@ mono_domain_finalize (MonoDomain *domain, guint32 timeout)
        if (timeout == -1)
                timeout = INFINITE;
 
-#if TARGET_WIN32
-       while (TRUE) {
-               guint32 res = guarded_wait (req->done_event, timeout, TRUE);
-               /* printf ("WAIT RES: %d.\n", res); */
-
-               if (res == WAIT_IO_COMPLETION) {
-                       if ((thread->state & (ThreadState_StopRequested | ThreadState_SuspendRequested)) != 0)
-                               return FALSE;
-               } else if (res == WAIT_TIMEOUT) {
-                       /* We leak the handle here */
-                       return FALSE;
-               } else {
+       for (;;) {
+               res = mono_coop_sem_timedwait (&req->done, timeout, MONO_SEM_FLAGS_ALERTABLE);
+               if (res == MONO_SEM_TIMEDWAIT_RET_SUCCESS) {
                        break;
-               }
-       }
-
-       CloseHandle (req->done_event);
-#else
-       mono_coop_mutex_lock (&req->mutex);
-       while (!req->done) {
-               gboolean alerted;
-               int res = coop_cond_timedwait_alertable (&req->cond, &req->mutex, timeout, &alerted);
-               if (alerted) {
-                       if ((thread->state & (ThreadState_StopRequested | ThreadState_SuspendRequested)) != 0) {
-                               mono_coop_mutex_unlock (&req->mutex);
+               } else if (res == MONO_SEM_TIMEDWAIT_RET_ALERTED) {
+                       if ((thread->state & (ThreadState_StopRequested | ThreadState_SuspendRequested)) != 0)
                                return FALSE;
-                       }
-               } else if (res == -1) {
-                       /* We leak the cond/mutex here */
-                       mono_coop_mutex_unlock (&req->mutex);
+               } else if (res == MONO_SEM_TIMEDWAIT_RET_TIMEDOUT) {
                        return FALSE;
                } else {
-                       break;
+                       g_error ("%s: unknown result %d", __func__, res);
                }
        }
-       mono_coop_mutex_unlock (&req->mutex);
 
        /* When we reach here, the other thread has already exited the critical section, so this is safe to free */
-       mono_coop_cond_destroy (&req->cond);
-       mono_coop_mutex_destroy (&req->mutex);
+       mono_coop_sem_destroy (&req->done);
        g_free (req);
-#endif
 
        if (domain == mono_get_root_domain ()) {
                mono_threadpool_ms_cleanup ();
@@ -806,17 +720,7 @@ finalize_domain_objects (DomainFinalizationReq *req)
        reference_queue_clear_for_domain (domain);
        
        /* printf ("DONE.\n"); */
-#if TARGET_WIN32
-       SetEvent (req->done_event);
-
-       /* The event is closed in mono_domain_finalize if we get here */
-       g_free (req);
-#else
-       mono_coop_mutex_lock (&req->mutex);
-       req->done = TRUE;
-       mono_coop_cond_signal (&req->cond);
-       mono_coop_mutex_unlock (&req->mutex);
-#endif
+       mono_coop_sem_post (&req->done);
 }
 
 static guint32