#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>
typedef struct {
gint32 ref;
- MonoCoopSem sem;
+ MonoCoopCond cond;
} ThreadPoolDomainCleanupSemaphore;
typedef enum {
MONITOR_STATUS_NOT_RUNNING,
};
-static MonoNativeThreadId monitor_tid;
static gint32 monitor_status = MONITOR_STATUS_NOT_RUNNING;
static ThreadPool* threadpool;
static void worker_kill (ThreadPoolWorkingThread *thread);
-static void monitor_kill (void);
-
static void
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);
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;
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);
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;
}
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;
}
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);
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);
} 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:
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;
}
}
-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)
{
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)) {
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);
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