[runtime] Move MonoClass::next_class_cache to MonoClassDef.
[mono.git] / mono / metadata / threadpool-ms.c
index 01ee391e575110c78a2fbb15d7ee479b695b8cf9..d22470415e84e1891759e5a31df748eacde76531 100644 (file)
@@ -33,6 +33,7 @@
 #include <mono/metadata/object-internals.h>
 #include <mono/metadata/threadpool-ms.h>
 #include <mono/metadata/threadpool-ms-io.h>
+#include <mono/metadata/w32event.h>
 #include <mono/utils/atomic.h>
 #include <mono/utils/mono-compiler.h>
 #include <mono/utils/mono-complex.h>
@@ -161,7 +162,7 @@ typedef struct {
 
 typedef struct {
        gint32 ref;
-       MonoCoopSem sem;
+       MonoCoopCond cond;
 } ThreadPoolDomainCleanupSemaphore;
 
 typedef enum {
@@ -184,7 +185,6 @@ enum {
        MONITOR_STATUS_NOT_RUNNING,
 };
 
-static MonoNativeThreadId monitor_tid;
 static gint32 monitor_status = MONITOR_STATUS_NOT_RUNNING;
 
 static ThreadPool* threadpool;
@@ -327,8 +327,6 @@ initialize (void)
 
 static void worker_kill (ThreadPoolWorkingThread *thread);
 
-static void monitor_kill (void);
-
 static void
 cleanup (void)
 {
@@ -338,7 +336,8 @@ cleanup (void)
         * cleaning up only if the runtime is shutting down */
        g_assert (mono_runtime_is_shutting_down ());
 
-       monitor_kill ();
+       while (monitor_status != MONITOR_STATUS_NOT_RUNNING)
+               mono_thread_info_sleep (1, NULL);
 
        mono_coop_mutex_lock (&threadpool->active_threads_lock);
 
@@ -440,7 +439,7 @@ domain_get (MonoDomain *domain, gboolean create)
                ThreadPoolDomainCleanupSemaphore *cleanup_semaphore;
                cleanup_semaphore = g_new0 (ThreadPoolDomainCleanupSemaphore, 1);
                cleanup_semaphore->ref = 2;
-               mono_coop_sem_init (&cleanup_semaphore->sem, 0);
+               mono_coop_cond_init (&cleanup_semaphore->cond);
 
                g_assert(!domain->cleanup_semaphore);
                domain->cleanup_semaphore = cleanup_semaphore;
@@ -659,7 +658,7 @@ worker_thread (gpointer data)
                tpdomain->outstanding_request --;
                g_assert (tpdomain->outstanding_request >= 0);
 
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] worker running in domain %p",
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] worker running in domain %p (outstanding requests %d) ",
                        mono_native_thread_id_get (), tpdomain->domain, tpdomain->outstanding_request);
 
                g_assert (tpdomain->domain);
@@ -703,11 +702,12 @@ worker_thread (gpointer data)
                        g_assert (removed);
 
                        cleanup_semaphore = (ThreadPoolDomainCleanupSemaphore*) tpdomain->domain->cleanup_semaphore;
+                       g_assert (cleanup_semaphore);
+
+                       mono_coop_cond_signal (&cleanup_semaphore->cond);
 
-                       g_assert(cleanup_semaphore);
-                       mono_coop_sem_post (&cleanup_semaphore->sem);
                        if (InterlockedDecrement (&cleanup_semaphore->ref) == 0) {
-                               mono_coop_sem_destroy (&cleanup_semaphore->sem);
+                               mono_coop_cond_destroy (&cleanup_semaphore->cond);
                                g_free (cleanup_semaphore);
                                tpdomain->domain->cleanup_semaphore = NULL;
                        }
@@ -778,7 +778,7 @@ worker_try_create (void)
        if ((thread = mono_thread_create_internal (mono_get_root_domain (), worker_thread, NULL, TRUE, 0, &error)) != NULL) {
                threadpool->worker_creation_current_count += 1;
 
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] try create worker, created %p, now = %d count = %d", mono_native_thread_id_get (), thread->tid, now, threadpool->worker_creation_current_count);
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] try create worker, created %p, now = %d count = %d", mono_native_thread_id_get (), GUINT_TO_POINTER(thread->tid), now, threadpool->worker_creation_current_count);
                mono_coop_mutex_unlock (&threadpool->worker_creation_lock);
                return TRUE;
        }
@@ -904,11 +904,11 @@ monitor_sufficient_delay_since_last_dequeue (void)
 
 static void hill_climbing_force_change (gint16 new_thread_count, ThreadPoolHeuristicStateTransition transition);
 
-static gsize WINAPI
-monitor_thread (gpointer unused G_GNUC_UNUSED)
+static void
+monitor_thread (void)
 {
+       MonoInternalThread *current_thread = mono_thread_internal_current ();
        guint i;
-       gboolean alerted;
 
        mono_cpu_usage (threadpool->cpu_usage_state);
 
@@ -926,22 +926,28 @@ monitor_thread (gpointer unused G_GNUC_UNUSED)
 
                do {
                        gint64 ts;
+                       gboolean alerted = FALSE;
 
-                       alerted = FALSE;
+                       if (mono_runtime_is_shutting_down ())
+                               break;
 
                        ts = mono_msec_ticks ();
                        if (mono_thread_info_sleep (interval_left, &alerted) == 0)
                                break;
-
                        interval_left -= mono_msec_ticks () - ts;
-               } while (!alerted && interval_left > 0 && ++awake < 10);
+
+                       mono_gc_set_skip_thread (FALSE);
+                       if ((current_thread->state & (ThreadState_StopRequested | ThreadState_SuspendRequested)) != 0)
+                               mono_thread_interruption_checkpoint ();
+                       mono_gc_set_skip_thread (TRUE);
+               } while (interval_left > 0 && ++awake < 10);
 
                mono_gc_set_skip_thread (FALSE);
 
-               if (mono_runtime_is_shutting_down ())
+               if (threadpool->suspended)
                        continue;
 
-               if (threadpool->suspended)
+               if (mono_runtime_is_shutting_down ())
                        continue;
 
                mono_coop_mutex_lock (&threadpool->domains_lock);
@@ -988,13 +994,12 @@ monitor_thread (gpointer unused G_GNUC_UNUSED)
        } while (monitor_should_keep_running ());
 
        mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] monitor thread, finished", mono_native_thread_id_get ());
-
-       return 0;
 }
 
 static void
 monitor_ensure_running (void)
 {
+       MonoError error;
        for (;;) {
                switch (monitor_status) {
                case MONITOR_STATUS_REQUESTED:
@@ -1006,20 +1011,10 @@ monitor_ensure_running (void)
                        if (mono_runtime_is_shutting_down ())
                                return;
                        if (InterlockedCompareExchange (&monitor_status, MONITOR_STATUS_REQUESTED, MONITOR_STATUS_NOT_RUNNING) == MONITOR_STATUS_NOT_RUNNING) {
-                               MonoThreadParm tp;
-                               gpointer handle;
-
-                               tp.priority = MONO_THREAD_PRIORITY_NORMAL;
-                               tp.stack_size = SMALL_STACK;
-                               tp.creation_flags = 0;
-                               handle = mono_threads_create_thread (monitor_thread, NULL, &tp, &monitor_tid);
-                               if (!handle) {
-                                       mono_atomic_store_release (&monitor_status, MONITOR_STATUS_NOT_RUNNING);
-                                       g_warning ("%s: failed to create monitor thread", __func__);
-                                       return;
+                               if (!mono_thread_create_internal (mono_get_root_domain (), monitor_thread, NULL, TRUE, SMALL_STACK, &error)) {
+                                       monitor_status = MONITOR_STATUS_NOT_RUNNING;
+                                       mono_error_cleanup (&error);
                                }
-
-                               mono_threads_close_thread_handle (handle);
                                return;
                        }
                        break;
@@ -1028,33 +1023,6 @@ monitor_ensure_running (void)
        }
 }
 
-static void
-monitor_kill (void)
-{
-       MonoThreadHazardPointers *hp;
-       MonoThreadInfo *info;
-       MonoThreadInfoInterruptToken *token;
-
-       if (!monitor_tid)
-               return;
-
-       hp = mono_hazard_pointer_get ();
-
-       info = mono_thread_info_lookup (monitor_tid);
-
-       if (!info)
-               goto cleanup;
-
-       token = mono_thread_info_prepare_interrupt (info);
-       mono_thread_info_finish_interrupt (token);
-
-       while (monitor_status != MONITOR_STATUS_NOT_RUNNING)
-               mono_thread_info_sleep (1, NULL);
-
-cleanup:
-       mono_hazard_pointer_clear (hp, 1);
-}
-
 static void
 hill_climbing_change_thread_count (gint16 new_thread_count, ThreadPoolHeuristicStateTransition transition)
 {
@@ -1460,7 +1428,7 @@ mono_threadpool_ms_end_invoke (MonoAsyncResult *ares, MonoArray **out_args, Mono
                if (ares->handle) {
                        wait_event = mono_wait_handle_get_handle ((MonoWaitHandle*) ares->handle);
                } else {
-                       wait_event = CreateEvent (NULL, TRUE, FALSE, NULL);
+                       wait_event = mono_w32event_create (TRUE, FALSE);
                        g_assert(wait_event);
                        MonoWaitHandle *wait_handle = mono_wait_handle_new (mono_object_domain (ares), wait_event, error);
                        if (!is_ok (error)) {
@@ -1486,10 +1454,10 @@ mono_threadpool_ms_end_invoke (MonoAsyncResult *ares, MonoArray **out_args, Mono
 gboolean
 mono_threadpool_ms_remove_domain_jobs (MonoDomain *domain, int timeout)
 {
-       gint res;
-       gint64 now, end;
+       gint64 end;
        ThreadPoolDomain *tpdomain;
        ThreadPoolDomainCleanupSemaphore *cleanup_semaphore;
+       gboolean ret;
 
        g_assert (domain);
        g_assert (timeout >= -1);
@@ -1526,29 +1494,41 @@ mono_threadpool_ms_remove_domain_jobs (MonoDomain *domain, int timeout)
                return TRUE;
        }
 
-       mono_coop_mutex_unlock(&threadpool->domains_lock);
-
        g_assert (domain->cleanup_semaphore);
-
        cleanup_semaphore = (ThreadPoolDomainCleanupSemaphore*) domain->cleanup_semaphore;
 
-       if (timeout == -1) {
-               res = mono_coop_sem_wait (&cleanup_semaphore->sem, MONO_SEM_FLAGS_NONE);
-               g_assert (res == MONO_SEM_TIMEDWAIT_RET_SUCCESS);
-       } else {
-               now = mono_msec_ticks();
-               if (now > end)
-                       return FALSE;
-               res = mono_coop_sem_timedwait (&cleanup_semaphore->sem, end - now, MONO_SEM_FLAGS_NONE);
-       }
+       ret = TRUE;
+
+       do {
+               if (timeout == -1) {
+                       mono_coop_cond_wait (&cleanup_semaphore->cond, &threadpool->domains_lock);
+               } else {
+                       gint64 now;
+                       gint res;
+
+                       now = mono_msec_ticks();
+                       if (now > end) {
+                               ret = FALSE;
+                               break;
+                       }
+
+                       res = mono_coop_cond_timedwait (&cleanup_semaphore->cond, &threadpool->domains_lock, end - now);
+                       if (res != 0) {
+                               ret = FALSE;
+                               break;
+                       }
+               }
+       } while (tpdomain->outstanding_request != 0);
 
        if (InterlockedDecrement (&cleanup_semaphore->ref) == 0) {
-               mono_coop_sem_destroy (&cleanup_semaphore->sem);
+               mono_coop_cond_destroy (&cleanup_semaphore->cond);
                g_free (cleanup_semaphore);
                domain->cleanup_semaphore = NULL;
        }
 
-       return res == MONO_SEM_TIMEDWAIT_RET_SUCCESS;
+       mono_coop_mutex_unlock(&threadpool->domains_lock);
+
+       return ret;
 }
 
 void