gint event_system;
gpointer event_data;
- void (*modify) (gpointer event_data, int fd, int operation, int events, gboolean is_new);
+ void (*modify) (gpointer p, int fd, int operation, int events, gboolean is_new);
void (*wait) (gpointer sock_data);
void (*shutdown) (gpointer event_data);
} SocketIOData;
static MonoObject *get_io_event (MonoMList **list, gint event);
static int get_events_from_list (MonoMList *list);
static int get_event_from_state (MonoSocketAsyncResult *state);
+static void check_for_interruption_critical (void);
static MonoClass *async_call_klass;
static MonoClass *socket_async_call_klass;
mono_g_hash_table_replace (data->sock_to_state, state->handle, list);
ievt = get_events_from_list (list);
- LeaveCriticalSection (&data->io_lock);
- data->modify (data->event_data, fd, state->operation, ievt, is_new);
+ /* The modify function leaves the io_lock critical section. */
+ data->modify (data, fd, state->operation, ievt, is_new);
}
#ifndef DISABLE_SOCKETS
ves_icall_System_Threading_Thread_SetName_internal (thread, mono_string_new (mono_domain_get (), "Threadpool monitor"));
while (1) {
ms = 500;
+ i = 10; //number of spurious awakes we tolerate before doing a round of rebalancing.
do {
guint32 ts;
ts = mono_msec_ticks ();
break;
if (THREAD_WANTS_A_BREAK (thread))
mono_thread_interruption_checkpoint ();
- } while (ms > 0);
+ } while (ms > 0 && i--);
if (mono_runtime_is_shutting_down ())
break;
}
void
-mono_thread_pool_init ()
+mono_thread_pool_init_tls (void)
+{
+ mono_wsq_init ();
+}
+
+void
+mono_thread_pool_init (void)
{
gint threads_per_cpu = 1;
gint thread_count;
InitializeCriticalSection (&wsqs_lock);
wsqs = g_ptr_array_sized_new (MAX (100 * cpu_count, thread_count));
- mono_wsq_init ();
#ifndef DISABLE_PERFCOUNTERS
async_tp.pc_nitems = init_perf_counter ("Mono Threadpool", "Work Items Added");
threadpool_clear_queue (ThreadPool *tp, MonoDomain *domain)
{
MonoObject *obj;
- MonoMList *other;
+ MonoMList *other = NULL;
+ MonoCQ *queue = tp->queue;
+
+ if (!queue)
+ return;
- other = NULL;
- while (mono_cq_dequeue (tp->queue, &obj)) {
+ while (mono_cq_dequeue (queue, &obj)) {
if (obj == NULL)
continue;
if (obj->vtable->domain != domain)
threadpool_jobs_dec (obj);
}
+ if (mono_runtime_is_shutting_down ())
+ return;
+
while (other) {
threadpool_append_job (tp, (MonoObject *) mono_mlist_get_data (other));
other = mono_mlist_next (other);
return result;
}
+static void
+set_tp_thread_info (ThreadPool *tp)
+{
+ const gchar *name;
+ MonoInternalThread *thread = mono_thread_internal_current ();
+
+ mono_profiler_thread_start (thread->tid);
+ name = (tp->is_io) ? "IO Threadpool worker" : "Threadpool worker";
+ mono_thread_set_name_internal (thread, mono_string_new (mono_domain_get (), name), FALSE);
+}
+
+static void
+clear_thread_state (void)
+{
+ MonoInternalThread *thread = mono_thread_internal_current ();
+ /* If the callee changes the background status, set it back to TRUE */
+ mono_thread_clr_state (thread , ~ThreadState_Background);
+ if (!mono_thread_test_state (thread , ThreadState_Background))
+ ves_icall_System_Threading_Thread_SetState (thread, ThreadState_Background);
+}
+
+static void
+check_for_interruption_critical (void)
+{
+ MonoInternalThread *thread;
+ /*RULE NUMBER ONE OF SKIP_THREAD: NEVER POKE MANAGED STATE.*/
+ mono_gc_set_skip_thread (FALSE);
+
+ thread = mono_thread_internal_current ();
+ if (THREAD_WANTS_A_BREAK (thread))
+ mono_thread_interruption_checkpoint ();
+
+ /*RULE NUMBER TWO OF SKIP_THREAD: READ RULE NUMBER ONE.*/
+ mono_gc_set_skip_thread (TRUE);
+}
+
+static void
+fire_profiler_thread_end (void)
+{
+ MonoInternalThread *thread = mono_thread_internal_current ();
+ mono_profiler_thread_end (thread->tid);
+}
+
static void
async_invoke_thread (gpointer data)
{
MonoDomain *domain;
- MonoInternalThread *thread;
MonoWSQ *wsq;
ThreadPool *tp;
gboolean must_die;
- const gchar *name;
tp = data;
wsq = NULL;
if (!tp->is_io)
wsq = add_wsq ();
- thread = mono_thread_internal_current ();
-
- mono_profiler_thread_start (thread->tid);
- name = (tp->is_io) ? "IO Threadpool worker" : "Threadpool worker";
- mono_thread_set_name_internal (thread, mono_string_new (mono_domain_get (), name), FALSE);
+ set_tp_thread_info (tp);
if (tp_start_func)
tp_start_func (tp_hooks_user_data);
}
mono_thread_pop_appdomain_ref ();
InterlockedDecrement (&tp->busy_threads);
- /* If the callee changes the background status, set it back to TRUE */
- mono_thread_clr_state (thread , ~ThreadState_Background);
- if (!mono_thread_test_state (thread , ThreadState_Background))
- ves_icall_System_Threading_Thread_SetState (thread, ThreadState_Background);
+ clear_thread_state ();
}
}
#endif
if (mono_runtime_is_shutting_down ())
break;
- if (THREAD_WANTS_A_BREAK (thread))
- mono_thread_interruption_checkpoint ();
+ check_for_interruption_critical ();
}
InterlockedDecrement (&tp->waiting);
remove_wsq (wsq);
}
- mono_profiler_thread_end (thread->tid);
+ fire_profiler_thread_end ();
if (tp_finish_func)
tp_finish_func (tp_hooks_user_data);