X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fthreadpool-ms.c;h=62fc34aef3f2b11e470b7a8912c819bbf68a6db1;hb=56ad8f4e5dfb8198e4671f631a3103b1e8b83dd3;hp=7d9657c2fcc61f229b54dca8a45e1af6388ad667;hpb=79ccd5ed96ba22b43ecb91797c51e19eada401f2;p=mono.git diff --git a/mono/metadata/threadpool-ms.c b/mono/metadata/threadpool-ms.c index 7d9657c2fcc..62fc34aef3f 100644 --- a/mono/metadata/threadpool-ms.c +++ b/mono/metadata/threadpool-ms.c @@ -5,6 +5,7 @@ * Ludovic Henry (ludovic.henry@xamarin.com) * * Copyright 2015 Xamarin, Inc (http://www.xamarin.com) + * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ // @@ -46,7 +47,7 @@ #define CPU_USAGE_LOW 80 #define CPU_USAGE_HIGH 95 -#define MONITOR_INTERVAL 100 // ms +#define MONITOR_INTERVAL 500 // ms #define MONITOR_MINIMAL_LIFETIME 60 * 1000 // ms #define WORKER_CREATION_MAX_PER_SEC 10 @@ -227,11 +228,11 @@ rand_create (void) static guint32 rand_next (gpointer *handle, guint32 min, guint32 max) { + MonoError error; guint32 val; - if (!mono_rand_try_get_uint32 (handle, &val, min, max)) { - // FIXME handle error - g_assert_not_reached (); - } + mono_rand_try_get_uint32 (handle, &val, min, max, &error); + // FIXME handle error + mono_error_assert_ok (&error); return val; } @@ -344,21 +345,20 @@ cleanup (void) mono_coop_mutex_unlock (&threadpool->active_threads_lock); } -void -mono_threadpool_ms_enqueue_work_item (MonoDomain *domain, MonoObject *work_item) +gboolean +mono_threadpool_ms_enqueue_work_item (MonoDomain *domain, MonoObject *work_item, MonoError *error) { static MonoClass *threadpool_class = NULL; static MonoMethod *unsafe_queue_custom_work_item_method = NULL; - MonoError error; MonoDomain *current_domain; MonoBoolean f; gpointer args [2]; + mono_error_init (error); g_assert (work_item); if (!threadpool_class) - threadpool_class = mono_class_from_name (mono_defaults.corlib, "System.Threading", "ThreadPool"); - g_assert (threadpool_class); + threadpool_class = mono_class_load_from_name (mono_defaults.corlib, "System.Threading", "ThreadPool"); if (!unsafe_queue_custom_work_item_method) unsafe_queue_custom_work_item_method = mono_class_get_method_from_name (threadpool_class, "UnsafeQueueCustomWorkItem", 2); @@ -371,17 +371,21 @@ mono_threadpool_ms_enqueue_work_item (MonoDomain *domain, MonoObject *work_item) current_domain = mono_domain_get (); if (current_domain == domain) { - mono_runtime_invoke_checked (unsafe_queue_custom_work_item_method, NULL, args, &error); - mono_error_raise_exception (&error); /* FIXME don't raise here */ + mono_runtime_invoke_checked (unsafe_queue_custom_work_item_method, NULL, args, error); + return_val_if_nok (error, FALSE); } else { mono_thread_push_appdomain_ref (domain); if (mono_domain_set (domain, FALSE)) { - mono_runtime_invoke_checked (unsafe_queue_custom_work_item_method, NULL, args, &error); - mono_error_raise_exception (&error); /* FIXME don't raise here */ + mono_runtime_invoke_checked (unsafe_queue_custom_work_item_method, NULL, args, error); + if (!is_ok (error)) { + mono_thread_pop_appdomain_ref (); + return FALSE; + } mono_domain_set (current_domain, TRUE); } mono_thread_pop_appdomain_ref (); } + return TRUE; } /* LOCKING: threadpool->domains_lock must be held */ @@ -525,7 +529,7 @@ worker_park (void) if (interrupted) goto done; - if (mono_coop_cond_timedwait (&threadpool->parked_threads_cond, &threadpool->active_threads_lock, rand_next ((void **)rand_handle, 5 * 1000, 60 * 1000)) != 0) + if (mono_coop_cond_timedwait (&threadpool->parked_threads_cond, &threadpool->active_threads_lock, rand_next (&rand_handle, 5 * 1000, 60 * 1000)) != 0) timeout = TRUE; mono_thread_info_uninstall_interrupt (&interrupted); @@ -876,8 +880,8 @@ monitor_thread (void) mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] monitor thread, started", mono_native_thread_id_get ()); do { - MonoInternalThread *thread; - gboolean all_waitsleepjoin = TRUE; + ThreadPoolCounter counter; + gboolean limit_worker_max_reached; gint32 interval_left = MONITOR_INTERVAL; gint32 awake = 0; /* number of spurious awakes we tolerate before doing a round of rebalancing */ @@ -918,49 +922,38 @@ monitor_thread (void) } mono_coop_mutex_unlock (&threadpool->domains_lock); + threadpool->cpu_usage = mono_cpu_usage (threadpool->cpu_usage_state); - mono_coop_mutex_lock (&threadpool->active_threads_lock); - for (i = 0; i < threadpool->working_threads->len; ++i) { - thread = (MonoInternalThread *)g_ptr_array_index (threadpool->working_threads, i); - if ((thread->state & ThreadState_WaitSleepJoin) == 0) { - all_waitsleepjoin = FALSE; - break; - } - } - mono_coop_mutex_unlock (&threadpool->active_threads_lock); + if (!monitor_sufficient_delay_since_last_dequeue ()) + continue; - if (all_waitsleepjoin) { - ThreadPoolCounter counter; - gboolean limit_worker_max_reached = FALSE; + limit_worker_max_reached = FALSE; - COUNTER_ATOMIC (counter, { - if (counter._.max_working >= threadpool->limit_worker_max) { - limit_worker_max_reached = TRUE; - break; - } - counter._.max_working ++; - }); + COUNTER_ATOMIC (counter, { + if (counter._.max_working >= threadpool->limit_worker_max) { + limit_worker_max_reached = TRUE; + break; + } + counter._.max_working ++; + }); - if (!limit_worker_max_reached) - hill_climbing_force_change (counter._.max_working, TRANSITION_STARVATION); - } + if (limit_worker_max_reached) + continue; - threadpool->cpu_usage = mono_cpu_usage (threadpool->cpu_usage_state); + hill_climbing_force_change (counter._.max_working, TRANSITION_STARVATION); - if (monitor_sufficient_delay_since_last_dequeue ()) { - for (i = 0; i < 5; ++i) { - if (mono_runtime_is_shutting_down ()) - break; + for (i = 0; i < 5; ++i) { + if (mono_runtime_is_shutting_down ()) + break; - if (worker_try_unpark ()) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] monitor thread, unparked", mono_native_thread_id_get ()); - break; - } + if (worker_try_unpark ()) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] monitor thread, unparked", mono_native_thread_id_get ()); + break; + } - if (worker_try_create ()) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] monitor thread, created", mono_native_thread_id_get ()); - break; - } + if (worker_try_create ()) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_THREADPOOL, "[%p] monitor thread, created", mono_native_thread_id_get ()); + break; } } } while (monitor_should_keep_running ()); @@ -1326,10 +1319,9 @@ mono_threadpool_ms_cleanup (void) } MonoAsyncResult * -mono_threadpool_ms_begin_invoke (MonoDomain *domain, MonoObject *target, MonoMethod *method, gpointer *params) +mono_threadpool_ms_begin_invoke (MonoDomain *domain, MonoObject *target, MonoMethod *method, gpointer *params, MonoError *error) { static MonoClass *async_call_klass = NULL; - MonoError error; MonoMethodMessage *message; MonoAsyncResult *async_result; MonoAsyncCall *async_call; @@ -1337,15 +1329,16 @@ mono_threadpool_ms_begin_invoke (MonoDomain *domain, MonoObject *target, MonoMet MonoObject *state = NULL; if (!async_call_klass) - async_call_klass = mono_class_from_name (mono_defaults.corlib, "System", "MonoAsyncCall"); - g_assert (async_call_klass); + async_call_klass = mono_class_load_from_name (mono_defaults.corlib, "System", "MonoAsyncCall"); mono_lazy_initialize (&status, initialize); + mono_error_init (error); + message = mono_method_call_message_new (method, params, mono_get_delegate_invoke (method->klass), (params != NULL) ? (&async_callback) : NULL, (params != NULL) ? (&state) : NULL); - async_call = (MonoAsyncCall*) mono_object_new_checked (domain, async_call_klass, &error); - mono_error_raise_exception (&error); /* FIXME don't raise here */ + async_call = (MonoAsyncCall*) mono_object_new_checked (domain, async_call_klass, error); + return_val_if_nok (error, NULL); MONO_OBJECT_SETREF (async_call, msg, message); MONO_OBJECT_SETREF (async_call, state, state); @@ -1358,7 +1351,8 @@ mono_threadpool_ms_begin_invoke (MonoDomain *domain, MonoObject *target, MonoMet async_result = mono_async_result_new (domain, NULL, async_call->state, NULL, (MonoObject*) async_call); MONO_OBJECT_SETREF (async_result, async_delegate, target); - mono_threadpool_ms_enqueue_work_item (domain, (MonoObject*) async_result); + mono_threadpool_ms_enqueue_work_item (domain, (MonoObject*) async_result, error); + return_val_if_nok (error, NULL); return async_result; } @@ -1596,7 +1590,9 @@ void ves_icall_System_Threading_ThreadPool_ReportThreadStatus (MonoBoolean is_working) { // TODO - mono_raise_exception (mono_get_exception_not_implemented (NULL)); + MonoError error; + mono_error_set_not_implemented (&error, ""); + mono_error_set_pending_exception (&error); } MonoBoolean @@ -1609,7 +1605,9 @@ MonoBoolean G_GNUC_UNUSED ves_icall_System_Threading_ThreadPool_PostQueuedCompletionStatus (MonoNativeOverlapped *native_overlapped) { /* This copy the behavior of the current Mono implementation */ - mono_raise_exception (mono_get_exception_not_implemented (NULL)); + MonoError error; + mono_error_set_not_implemented (&error, ""); + mono_error_set_pending_exception (&error); return FALSE; }