static SgenThreadPoolIdleJobFunc idle_job_func;
static SgenThreadPoolContinueIdleJobFunc continue_idle_job_func;
+static volatile gboolean threadpool_shutdown;
+static volatile gboolean thread_finished;
+
enum {
STATE_WAITING,
STATE_IN_PROGRESS,
gboolean do_idle = continue_idle_job ();
SgenThreadPoolJob *job = get_job_and_set_in_progress ();
- if (!job && !do_idle) {
+ if (!job && !do_idle && !threadpool_shutdown) {
/*
* pthread_cond_wait() can return successfully despite the condition
* not being signalled, so we have to run this in a loop until we
* have to broadcast.
*/
mono_os_cond_signal (&done_cond);
- } else {
- SGEN_ASSERT (0, do_idle, "Why did we unlock if we still have to wait for idle?");
+ } else if (do_idle) {
SGEN_ASSERT (0, idle_job_func, "Why do we have idle work when there's no idle job function?");
do {
idle_job_func (thread_data);
if (!do_idle)
mono_os_cond_signal (&done_cond);
+ } else {
+ SGEN_ASSERT (0, threadpool_shutdown, "Why did we unlock if no jobs and not shutting down?");
+ mono_os_mutex_lock (&lock);
+ thread_finished = TRUE;
+ mono_os_cond_signal (&done_cond);
+ mono_os_mutex_unlock (&lock);
+ return 0;
}
}
mono_native_thread_create (&thread, thread_func, thread_datas ? thread_datas [0] : NULL);
}
+void
+sgen_thread_pool_shutdown (void)
+{
+ if (!thread)
+ return;
+
+ mono_os_mutex_lock (&lock);
+ threadpool_shutdown = TRUE;
+ mono_os_cond_signal (&work_cond);
+ while (!thread_finished)
+ mono_os_cond_wait (&done_cond, &lock);
+ mono_os_mutex_unlock (&lock);
+
+ mono_os_mutex_destroy (&lock);
+ mono_os_cond_destroy (&work_cond);
+ mono_os_cond_destroy (&done_cond);
+}
+
SgenThreadPoolJob*
sgen_thread_pool_job_alloc (const char *name, SgenThreadPoolJobFunc func, size_t size)
{