Пример #1
0
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);
		}
	}
}
Пример #2
0
void
sgen_thread_pool_idle_signal (void)
{
	SGEN_ASSERT (0, idle_job_func, "Why are we signaling idle without an idle function?");

	mono_mutex_lock (&lock);

	if (continue_idle_job_func ())
		mono_cond_signal (&work_cond);

	mono_mutex_unlock (&lock);
}
Пример #3
0
void
sgen_thread_pool_job_enqueue (SgenThreadPoolJob *job)
{
	mono_mutex_lock (&lock);

	sgen_pointer_queue_add (&job_queue, job);
	/*
	 * FIXME: We could check whether there is a job in progress.  If there is, there's
	 * no need to signal the condition, at least as long as we have only one thread.
	 */
	mono_cond_signal (&work_cond);

	mono_mutex_unlock (&lock);
}
Пример #4
0
static gboolean
worker_try_unpark (void)
{
	gboolean res = FALSE;
	guint len;

	mono_mutex_lock (&threadpool->parked_threads_lock);
	len = threadpool->parked_threads->len;
	if (len > 0) {
		mono_cond_t *cond = (mono_cond_t*) g_ptr_array_index (threadpool->parked_threads, len - 1);
		mono_cond_signal (cond);
		res = TRUE;
	}
	mono_mutex_unlock (&threadpool->parked_threads_lock);
	return res;
}
Пример #5
0
static void
ensure_cleanedup (void)
{
	if (status == STATUS_NOT_INITIALIZED && InterlockedCompareExchange (&status, STATUS_CLEANED_UP, STATUS_NOT_INITIALIZED) == STATUS_NOT_INITIALIZED)
		return;
	if (status == STATUS_INITIALIZING) {
		while (status == STATUS_INITIALIZING)
			mono_thread_info_yield ();
	}
	if (status == STATUS_CLEANED_UP)
		return;
	if (status == STATUS_CLEANING_UP || InterlockedCompareExchange (&status, STATUS_CLEANING_UP, STATUS_INITIALIZED) != STATUS_INITIALIZED) {
		while (status == STATUS_CLEANING_UP)
			mono_thread_info_yield ();
		g_assert (status == STATUS_CLEANED_UP);
		return;
	}

	/* we make the assumption along the code that we are
	 * cleaning up only if the runtime is shutting down */
	g_assert (mono_runtime_is_shutting_down ());

	/* Unpark all worker threads */
	mono_mutex_lock (&threadpool->parked_threads_lock);
	for (;;) {
		guint i;
		ThreadPoolCounter counter = COUNTER_READ ();
		if (counter._.active == 0 && counter._.parked == 0)
			break;
		if (counter._.active == 1) {
			MonoInternalThread *thread = mono_thread_internal_current ();
			if (thread->threadpool_thread) {
				/* if there is only one active thread
				 * left and it's the current one */
				break;
			}
		}
		for (i = 0; i < threadpool->parked_threads->len; ++i) {
			mono_cond_t *cond = (mono_cond_t*) g_ptr_array_index (threadpool->parked_threads, i);
			mono_cond_signal (cond);
		}
		mono_mutex_unlock (&threadpool->parked_threads_lock);
		usleep (1000);
		mono_mutex_lock (&threadpool->parked_threads_lock);
	}
	mono_mutex_unlock (&threadpool->parked_threads_lock);

	while (monitor_status != MONITOR_STATUS_NOT_RUNNING)
		usleep (1000);

	g_ptr_array_free (threadpool->domains, TRUE);
	mono_mutex_destroy (&threadpool->domains_lock);

	g_ptr_array_free (threadpool->parked_threads, TRUE);
	mono_mutex_destroy (&threadpool->parked_threads_lock);

	g_ptr_array_free (threadpool->working_threads, TRUE);
	mono_mutex_destroy (&threadpool->working_threads_lock);

	mono_mutex_destroy (&threadpool->heuristic_lock);
	g_free (threadpool->heuristic_hill_climbing.samples);
	g_free (threadpool->heuristic_hill_climbing.thread_counts);
	rand_free (threadpool->heuristic_hill_climbing.random_interval_generator);

	g_free (threadpool->cpu_usage_state);

	g_assert (threadpool);
	g_free (threadpool);
	threadpool = NULL;
	g_assert (!threadpool);

	status = STATUS_CLEANED_UP;
}