[threadpool] Use threadpool->threads instead of threadpool->counters to wait on clean...
[mono.git] / mono / metadata / threadpool.c
index ab88e67f4b960c6de4e6d2e52e3f38edd3cd7b29..07db889f26c197b15d71ab64d6992797c6381859 100644 (file)
@@ -87,22 +87,17 @@ static mono_lazy_init_t status = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED;
 
 static ThreadPool* threadpool;
 
-#define COUNTER_CHECK(counter) \
-       do { \
-               g_assert (sizeof (ThreadPoolCounter) == sizeof (gint32)); \
-               g_assert (counter._.starting >= 0); \
-               g_assert (counter._.working >= 0); \
-       } while (0)
-
 #define COUNTER_ATOMIC(threadpool,var,block) \
        do { \
                ThreadPoolCounter __old; \
                do { \
                        g_assert (threadpool); \
-                       __old = COUNTER_READ (threadpool); \
-                       (var) = __old; \
+                       (var) = __old = COUNTER_READ (threadpool); \
                        { block; } \
-                       COUNTER_CHECK (var); \
+                       if (!(counter._.starting >= 0)) \
+                               g_error ("%s: counter._.starting = %d, but should be >= 0", __func__, counter._.starting); \
+                       if (!(counter._.working >= 0)) \
+                               g_error ("%s: counter._.working = %d, but should be >= 0", __func__, counter._.working); \
                } while (InterlockedCompareExchange (&threadpool->counters.as_gint32, (var).as_gint32, __old.as_gint32) != __old.as_gint32); \
        } while (0)
 
@@ -146,6 +141,8 @@ initialize (void)
        threadpool = g_new0 (ThreadPool, 1);
        g_assert (threadpool);
 
+       g_assert (sizeof (ThreadPoolCounter) == sizeof (gint32));
+
        mono_refcount_init (threadpool, destroy);
 
        threadpool->domains = g_ptr_array_new ();
@@ -190,17 +187,12 @@ cleanup (void)
        mono_coop_mutex_lock (&threadpool->threads_lock);
 
        for (;;) {
-               ThreadPoolCounter counter;
-
-               counter = COUNTER_READ (threadpool);
-               if (counter._.working == 0)
+               if (threadpool->threads->len == 0)
                        break;
 
-               if (counter._.working == 1) {
-                       if (threadpool->threads->len == 1 && g_ptr_array_index (threadpool->threads, 0) == current) {
-                               /* We are waiting on ourselves */
-                               break;
-                       }
+               if (threadpool->threads->len == 1 && g_ptr_array_index (threadpool->threads, 0) == current) {
+                       /* We are waiting on ourselves */
+                       break;
                }
 
                mono_coop_cond_wait (&threadpool->threads_exit_cond, &threadpool->threads_lock);
@@ -359,6 +351,9 @@ worker_callback (gpointer unused)
        thread = mono_thread_internal_current ();
 
        COUNTER_ATOMIC (threadpool, counter, {
+               if (!(counter._.working < 32767 /* G_MAXINT16 */))
+                       g_error ("%s: counter._.working = %d, but should be < 32767", __func__, counter._.working);
+
                counter._.starting --;
                counter._.working ++;
        });
@@ -458,16 +453,16 @@ worker_callback (gpointer unused)
 
        mono_coop_mutex_lock (&threadpool->threads_lock);
 
-       COUNTER_ATOMIC (threadpool, counter, {
-               counter._.working --;
-       });
-
        g_ptr_array_remove_fast (threadpool->threads, thread);
 
        mono_coop_cond_signal (&threadpool->threads_exit_cond);
 
        mono_coop_mutex_unlock (&threadpool->threads_lock);
 
+       COUNTER_ATOMIC (threadpool, counter, {
+               counter._.working --;
+       });
+
        mono_refcount_dec (threadpool);
 }
 
@@ -607,12 +602,18 @@ mono_threadpool_remove_domain_jobs (MonoDomain *domain, int timeout)
         * The is_unloading () check in worker_request () ensures that
         * no new jobs are added after we enter the lock below.
         */
-       mono_lazy_initialize (&status, initialize);
+
+       if (!mono_lazy_is_initialized (&status))
+               return TRUE;
+
+       mono_refcount_inc (threadpool);
+
        domains_lock ();
 
        tpdomain = tpdomain_get (domain, FALSE);
        if (!tpdomain) {
                domains_unlock ();
+               mono_refcount_dec (threadpool);
                return TRUE;
        }
 
@@ -647,6 +648,8 @@ mono_threadpool_remove_domain_jobs (MonoDomain *domain, int timeout)
        mono_coop_cond_destroy (&tpdomain->cleanup_cond);
        tpdomain_free (tpdomain);
 
+       mono_refcount_dec (threadpool);
+
        return ret;
 }
 
@@ -801,6 +804,9 @@ ves_icall_System_Threading_ThreadPool_RequestWorkerThread (void)
        mono_refcount_inc (threadpool);
 
        COUNTER_ATOMIC (threadpool, counter, {
+               if (!(counter._.starting < 32767 /* G_MAXINT16 */))
+                       g_error ("%s: counter._.starting = %d, but should be < 32767", __func__, counter._.starting);
+
                counter._.starting ++;
        });