static mono_native_thread_return_t thread_func (void *thread_data) { thread_init_func (thread_data); mono_mutex_lock (&lock); for (;;) { /* * It's important that we check the continue idle flag with the lock held. * Suppose we didn't check with the lock held, and the result is FALSE. The * main thread might then set continue idle and signal us before we can take * the lock, and we'd lose the signal. */ gboolean do_idle = continue_idle_job (); SgenThreadPoolJob *job = get_job_and_set_in_progress (); if (!job && !do_idle) { /* * pthread_cond_wait() can return successfully despite the condition * not being signalled, so we have to run this in a loop until we * really have work to do. */ mono_cond_wait (&work_cond, &lock); continue; } mono_mutex_unlock (&lock); if (job) { job->func (thread_data, job); mono_mutex_lock (&lock); SGEN_ASSERT (0, job->state == STATE_IN_PROGRESS, "The job should still be in progress."); job->state = STATE_DONE; remove_job (job); /* * Only the main GC thread will ever wait on the done condition, so we don't * have to broadcast. */ mono_cond_signal (&done_cond); } else { SGEN_ASSERT (0, do_idle, "Why did we unlock if we still have to wait for 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); do_idle = continue_idle_job (); } while (do_idle && !job_queue.next_slot); mono_mutex_lock (&lock); if (!do_idle) mono_cond_signal (&done_cond); } } }
void sgen_thread_pool_wait_for_all_jobs (void) { mono_mutex_lock (&lock); while (!sgen_pointer_queue_is_empty (&job_queue)) mono_cond_wait (&done_cond, &lock); mono_mutex_unlock (&lock); }
void sgen_thread_pool_idle_wait (void) { SGEN_ASSERT (0, idle_job_func, "Why are we waiting for idle without an idle function?"); mono_mutex_lock (&lock); while (continue_idle_job_func ()) mono_cond_wait (&done_cond, &lock); mono_mutex_unlock (&lock); }
void sgen_thread_pool_job_wait (SgenThreadPoolJob *job) { SGEN_ASSERT (0, job, "Where's the job?"); mono_mutex_lock (&lock); while (find_job_in_queue (job) >= 0) mono_cond_wait (&done_cond, &lock); mono_mutex_unlock (&lock); }
static void worker_park (void) { mono_cond_t cond; mono_cond_init (&cond, NULL); mono_mutex_lock (&threadpool->parked_threads_lock); g_ptr_array_add (threadpool->parked_threads, &cond); mono_cond_wait (&cond, &threadpool->parked_threads_lock); g_ptr_array_remove (threadpool->parked_threads, &cond); mono_mutex_unlock (&threadpool->parked_threads_lock); mono_cond_destroy (&cond); }
/* Locking: threadpool_io->updates_lock must be held */ static ThreadPoolIOUpdate* update_get_new (void) { ThreadPoolIOUpdate *update = NULL; g_assert (threadpool_io->updates_size <= UPDATES_CAPACITY); while (threadpool_io->updates_size == UPDATES_CAPACITY) { /* we wait for updates to be applied in the selector_thread and we loop * as long as none are available. if it happends too much, then we need * to increase UPDATES_CAPACITY */ mono_cond_wait (&threadpool_io->updates_cond, &threadpool_io->updates_lock); } g_assert (threadpool_io->updates_size < UPDATES_CAPACITY); update = &threadpool_io->updates [threadpool_io->updates_size ++]; return update; }
void mono_threadpool_ms_io_remove_domain_jobs (MonoDomain *domain) { ThreadPoolIOUpdate *update; if (!mono_lazy_is_initialized (&io_status)) return; mono_mutex_lock (&threadpool_io->updates_lock); update = update_get_new (); update->type = UPDATE_REMOVE_DOMAIN; update->data.remove_domain.domain = domain; mono_memory_barrier (); /* Ensure this is safely published before we wake up the selector */ selector_thread_wakeup (); mono_cond_wait (&threadpool_io->updates_cond, &threadpool_io->updates_lock); mono_mutex_unlock (&threadpool_io->updates_lock); }
void mono_threadpool_ms_io_remove_socket (int fd) { ThreadPoolIOUpdate *update; if (!mono_lazy_is_initialized (&io_status)) return; mono_mutex_lock (&threadpool_io->updates_lock); update = update_get_new (); update->type = UPDATE_REMOVE_SOCKET; update->data.add.fd = fd; mono_memory_barrier (); /* Ensure this is safely published before we wake up the selector */ selector_thread_wakeup (); mono_cond_wait (&threadpool_io->updates_cond, &threadpool_io->updates_lock); mono_mutex_unlock (&threadpool_io->updates_lock); }