void mono_thread_pool_cleanup (void) { if (InterlockedExchange (&async_io_tp.pool_status, 2) == 1) { socket_io_cleanup (&socket_io_data); /* Empty when DISABLE_SOCKETS is defined */ threadpool_kill_idle_threads (&async_io_tp); } if (async_io_tp.queue != NULL) { MONO_SEM_DESTROY (&async_io_tp.new_job); threadpool_free_queue (&async_io_tp); } if (InterlockedExchange (&async_tp.pool_status, 2) == 1) { threadpool_kill_idle_threads (&async_tp); threadpool_free_queue (&async_tp); } if (wsqs) { EnterCriticalSection (&wsqs_lock); mono_wsq_cleanup (); if (wsqs) g_ptr_array_free (wsqs, TRUE); wsqs = NULL; LeaveCriticalSection (&wsqs_lock); MONO_SEM_DESTROY (&async_tp.new_job); } }
HANDLE mono_threads_core_create_thread (LPTHREAD_START_ROUTINE start_routine, gpointer arg, guint32 stack_size, guint32 creation_flags, MonoNativeThreadId *out_tid) { pthread_attr_t attr; int res; pthread_t thread; StartInfo start_info; res = pthread_attr_init (&attr); g_assert (!res); if (stack_size == 0) { #if HAVE_VALGRIND_MEMCHECK_H if (RUNNING_ON_VALGRIND) stack_size = 1 << 20; else stack_size = (SIZEOF_VOID_P / 4) * 1024 * 1024; #else stack_size = (SIZEOF_VOID_P / 4) * 1024 * 1024; #endif } #ifdef PTHREAD_STACK_MIN if (stack_size < PTHREAD_STACK_MIN) stack_size = PTHREAD_STACK_MIN; #endif #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE res = pthread_attr_setstacksize (&attr, stack_size); g_assert (!res); #endif memset (&start_info, 0, sizeof (StartInfo)); start_info.start_routine = (void *(*)(void *)) start_routine; start_info.arg = arg; start_info.flags = creation_flags; MONO_SEM_INIT (&(start_info.registered), 0); /* Actually start the thread */ res = mono_gc_pthread_create (&thread, &attr, inner_start_thread, &start_info); if (res) { MONO_SEM_DESTROY (&(start_info.registered)); return NULL; } MONO_TRY_BLOCKING; /* Wait until the thread register itself in various places */ while (MONO_SEM_WAIT (&(start_info.registered)) != 0) { /*if (EINTR != errno) ABORT("sem_wait failed"); */ } MONO_FINISH_TRY_BLOCKING; MONO_SEM_DESTROY (&(start_info.registered)); if (out_tid) *out_tid = thread; return start_info.handle; }
static void free_thread_info (gpointer mem) { MonoThreadInfo *info = mem; MONO_SEM_DESTROY (&info->suspend_semaphore); MONO_SEM_DESTROY (&info->resume_semaphore); MONO_SEM_DESTROY (&info->finish_resume_semaphore); mono_threads_platform_free (info); g_free (info); }
void _wapi_thread_set_termination_details (gpointer handle, guint32 exitstatus) { struct _WapiHandle_thread *thread_handle; gboolean ok; int thr_ret; if (_wapi_handle_issignalled (handle) || _wapi_handle_type (handle) == WAPI_HANDLE_UNUSED) { /* We must have already deliberately finished with * this thread, so don't do any more now */ return; } #ifdef DEBUG g_message ("%s: Thread %p terminating", __func__, handle); #endif _wapi_thread_abandon_mutexes (handle); ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD, (gpointer *)&thread_handle); if (ok == FALSE) { g_warning ("%s: error looking up thread handle %p", __func__, handle); return; } pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle, handle); thr_ret = _wapi_handle_lock_handle (handle); g_assert (thr_ret == 0); thread_handle->exitstatus = exitstatus; thread_handle->state = THREAD_STATE_EXITED; MONO_SEM_DESTROY (&thread_handle->suspend_sem); g_ptr_array_free (thread_handle->owned_mutexes, TRUE); _wapi_handle_set_signal_state (handle, TRUE, TRUE); thr_ret = _wapi_handle_unlock_handle (handle); g_assert (thr_ret == 0); pthread_cleanup_pop (0); #ifdef DEBUG g_message("%s: Recording thread handle %p id %ld status as %d", __func__, handle, thread_handle->id, exitstatus); #endif /* The thread is no longer active, so unref it */ _wapi_handle_unref (handle); }
void mono_thread_pool_cleanup (void) { if (InterlockedExchange (&async_io_tp.pool_status, 2) == 1) { socket_io_cleanup (&socket_io_data); /* Empty when DISABLE_SOCKETS is defined */ threadpool_kill_idle_threads (&async_io_tp); } if (async_io_tp.queue != NULL) { MONO_SEM_DESTROY (&async_io_tp.new_job); threadpool_free_queue (&async_io_tp); } if (InterlockedExchange (&async_tp.pool_status, 2) == 1) { threadpool_kill_idle_threads (&async_tp); threadpool_free_queue (&async_tp); } if (threads) { mono_mutex_lock (&threads_lock); if (threads) g_ptr_array_free (threads, FALSE); threads = NULL; mono_mutex_unlock (&threads_lock); } if (wsqs) { mono_mutex_lock (&wsqs_lock); mono_wsq_cleanup (); if (wsqs) g_ptr_array_free (wsqs, TRUE); wsqs = NULL; mono_mutex_unlock (&wsqs_lock); MONO_SEM_DESTROY (&async_tp.new_job); } MONO_SEM_DESTROY (&monitor_sem); }
static void* inner_start_thread (void *arg) { StartInfo *start_info = (StartInfo *) arg; void *t_arg = start_info->arg; int res; void *(*start_func)(void*) = start_info->start_routine; guint32 flags = start_info->flags; void *result; HANDLE handle; MonoThreadInfo *info; /* Register the thread with the io-layer */ handle = wapi_create_thread_handle (); if (!handle) { res = MONO_SEM_POST (&(start_info->registered)); g_assert (!res); return NULL; } start_info->handle = handle; info = mono_thread_info_attach (&result); MONO_PREPARE_BLOCKING info->runtime_thread = TRUE; info->handle = handle; if (flags & CREATE_SUSPENDED) { info->create_suspended = TRUE; MONO_SEM_INIT (&info->create_suspended_sem, 0); } /* start_info is not valid after this */ res = MONO_SEM_POST (&(start_info->registered)); g_assert (!res); start_info = NULL; if (flags & CREATE_SUSPENDED) { while (MONO_SEM_WAIT (&info->create_suspended_sem) != 0 && errno == EINTR); MONO_SEM_DESTROY (&info->create_suspended_sem); } MONO_FINISH_BLOCKING /* Run the actual main function of the thread */ result = start_func (t_arg); mono_threads_core_exit (GPOINTER_TO_UINT (result)); g_assert_not_reached (); }
static void tp_poll_shutdown (gpointer event_data) { tp_poll_data *data = event_data; #ifdef HOST_WIN32 closesocket (data->pipe [0]); closesocket (data->pipe [1]); #else if (data->pipe [0] > -1) close (data->pipe [0]); if (data->pipe [1] > -1) close (data->pipe [1]); #endif data->pipe [0] = -1; data->pipe [1] = -1; MONO_SEM_DESTROY (&data->new_sem); }
HANDLE mono_threads_core_create_thread (LPTHREAD_START_ROUTINE start_routine, gpointer arg, guint32 stack_size, guint32 creation_flags, MonoNativeThreadId *out_tid) { ThreadStartInfo *start_info; HANDLE result; DWORD thread_id; start_info = g_malloc0 (sizeof (ThreadStartInfo)); if (!start_info) return NULL; MONO_SEM_INIT (&(start_info->registered), 0); start_info->arg = arg; start_info->start_routine = start_routine; start_info->suspend = creation_flags & CREATE_SUSPENDED; creation_flags &= ~CREATE_SUSPENDED; if (start_info->suspend) { start_info->suspend_event = CreateEvent (NULL, TRUE, FALSE, NULL); if (!start_info->suspend_event) return NULL; } result = CreateThread (NULL, stack_size, inner_start_thread, start_info, creation_flags, &thread_id); if (result) { while (MONO_SEM_WAIT (&(start_info->registered)) != 0) { /*if (EINTR != errno) ABORT("sem_wait failed"); */ } if (start_info->suspend) { g_assert (SuspendThread (result) != (DWORD)-1); SetEvent (start_info->suspend_event); } } else if (start_info->suspend) { CloseHandle (start_info->suspend_event); } if (out_tid) *out_tid = thread_id; MONO_SEM_DESTROY (&(start_info->registered)); g_free (start_info); return result; }
int mono_threads_pthread_create (pthread_t *new_thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg) { ThreadStartInfo *start_info; int result; start_info = g_malloc0 (sizeof (ThreadStartInfo)); if (!start_info) return ENOMEM; MONO_SEM_INIT (&(start_info->registered), 0); start_info->arg = arg; start_info->start_routine = start_routine; result = mono_threads_get_callbacks ()->mono_gc_pthread_create (new_thread, attr, inner_start_thread, start_info); if (result == 0) { while (MONO_SEM_WAIT (&(start_info->registered)) != 0) { /*if (EINTR != errno) ABORT("sem_wait failed"); */ } } MONO_SEM_DESTROY (&(start_info->registered)); g_free (start_info); return result; }
static void* inner_start_thread (void *arg) { StartInfo *start_info = arg; void *t_arg = start_info->arg; int res; void *(*start_func)(void*) = start_info->start_routine; guint32 flags = start_info->flags; void *result; HANDLE handle; MonoThreadInfo *info; /* Register the thread with the io-layer */ handle = wapi_create_thread_handle (); if (!handle) { res = MONO_SEM_POST (&(start_info->registered)); g_assert (!res); return NULL; } start_info->handle = handle; info = mono_thread_info_attach (&result); info->runtime_thread = TRUE; info->handle = handle; if (flags & CREATE_SUSPENDED) { info->create_suspended = TRUE; MONO_SEM_INIT (&info->create_suspended_sem, 0); } /* start_info is not valid after this */ res = MONO_SEM_POST (&(start_info->registered)); g_assert (!res); start_info = NULL; if (flags & CREATE_SUSPENDED) { while (MONO_SEM_WAIT (&info->create_suspended_sem) != 0 && errno == EINTR); MONO_SEM_DESTROY (&info->create_suspended_sem); } /* Run the actual main function of the thread */ result = start_func (t_arg); /* mono_thread_info_detach (); */ #if defined(__native_client__) nacl_shutdown_gc_thread(); #endif wapi_thread_handle_set_exited (handle, GPOINTER_TO_UINT (result)); /* This is needed by mono_threads_core_unregister () which is called later */ info->handle = NULL; g_assert (mono_threads_get_callbacks ()->thread_exit); mono_threads_get_callbacks ()->thread_exit (NULL); g_assert_not_reached (); return result; }
void mono_threads_platform_free (MonoThreadInfo *info) { MONO_SEM_DESTROY (&info->begin_suspend_semaphore); }