Exemplo n.º 1
0
static gboolean
workers_get_work (WorkerData *data)
{
	int i;

	g_assert (gray_object_queue_is_empty (&data->private_gray_queue));

	/* Try to steal from our own stack. */
	if (workers_steal (data, data, TRUE))
		return TRUE;

	/* Then from the GC thread's stack. */
	if (workers_steal (data, &workers_gc_thread_data, TRUE))
		return TRUE;

	/* Finally, from another worker. */
	for (i = 0; i < workers_num; ++i) {
		WorkerData *victim_data = &workers_data [i];
		if (data == victim_data)
			continue;
		if (workers_steal (data, victim_data, TRUE))
			return TRUE;
	}

	/* Nobody to steal from */
	g_assert (gray_object_queue_is_empty (&data->private_gray_queue));
	return FALSE;
}
Exemplo n.º 2
0
static void
workers_join (void)
{
	int i;

	if (!collection_is_parallel ())
		return;

	g_assert (gray_object_queue_is_empty (&workers_gc_thread_data.private_gray_queue));
	g_assert (gray_object_queue_is_empty (&workers_distribute_gray_queue));

	g_assert (workers_gc_in_progress);
	workers_gc_in_progress = FALSE;
	if (workers_num_waiting == workers_num) {
		/*
		 * All the workers might have shut down at this point
		 * and posted the done semaphore but we don't know it
		 * yet.  It's not a big deal to wake them up again -
		 * they'll just do one iteration of their loop trying to
		 * find something to do and then go back to waiting
		 * again.
		 */
		workers_wake_up_all ();
	}
	MONO_SEM_WAIT (&workers_done_sem);
	workers_marking = FALSE;

	if (major_collector.reset_worker_data) {
		for (i = 0; i < workers_num; ++i)
			major_collector.reset_worker_data (workers_data [i].major_collector_data);
	}

	g_assert (workers_done_posted);

	g_assert (!workers_gc_thread_data.stealable_stack_fill);
	g_assert (gray_object_queue_is_empty (&workers_gc_thread_data.private_gray_queue));
	for (i = 0; i < workers_num; ++i) {
		g_assert (!workers_data [i].stealable_stack_fill);
		g_assert (gray_object_queue_is_empty (&workers_data [i].private_gray_queue));
	}
}
Exemplo n.º 3
0
static void*
workers_thread_func (void *data_untyped)
{
	WorkerData *data = data_untyped;

	mono_thread_info_register_small_id ();

	if (major_collector.init_worker_thread)
		major_collector.init_worker_thread (data->major_collector_data);

	gray_object_queue_init_with_alloc_prepare (&data->private_gray_queue,
			workers_gray_queue_share_redirect, data);

	for (;;) {
		gboolean did_work = FALSE;

		while (workers_dequeue_and_do_job (data)) {
			did_work = TRUE;
			/* FIXME: maybe distribute the gray queue here? */
		}

		if (workers_marking && (!gray_object_queue_is_empty (&data->private_gray_queue) || workers_get_work (data))) {
			g_assert (!gray_object_queue_is_empty (&data->private_gray_queue));

			while (!drain_gray_stack (&data->private_gray_queue, 32))
				workers_gray_queue_share_redirect (&data->private_gray_queue);
			g_assert (gray_object_queue_is_empty (&data->private_gray_queue));

			gray_object_queue_init (&data->private_gray_queue);

			did_work = TRUE;
		}

		if (!did_work)
			workers_wait ();
	}

	/* dummy return to make compilers happy */
	return NULL;
}
Exemplo n.º 4
0
static void
workers_gray_queue_share_redirect (GrayQueue *queue)
{
	GrayQueueSection *section;
	WorkerData *data = queue->alloc_prepare_data;

	if (data->stealable_stack_fill) {
		/*
		 * There are still objects in the stealable stack, so
		 * wake up any workers that might be sleeping
		 */
		if (workers_gc_in_progress)
			workers_wake_up_all ();
		return;
	}

	/* The stealable stack is empty, so fill it. */
	pthread_mutex_lock (&data->stealable_stack_mutex);

	while (data->stealable_stack_fill < STEALABLE_STACK_SIZE &&
			(section = gray_object_dequeue_section (queue))) {
		int num = MIN (section->end, STEALABLE_STACK_SIZE - data->stealable_stack_fill);

		memcpy (data->stealable_stack + data->stealable_stack_fill,
				section->objects + section->end - num,
				sizeof (char*) * num);

		section->end -= num;
		data->stealable_stack_fill += num;

		if (section->end)
			gray_object_enqueue_section (queue, section);
		else
			gray_object_free_queue_section (section);
	}

	if (data != &workers_gc_thread_data && gray_object_queue_is_empty (queue))
		workers_steal (data, data, FALSE);

	pthread_mutex_unlock (&data->stealable_stack_mutex);

	if (workers_gc_in_progress)
		workers_wake_up_all ();
}
Exemplo n.º 5
0
static void
gray_object_queue_init (GrayQueue *queue)
{
    GrayQueueSection *section, *next;
    int i;

    g_assert (gray_object_queue_is_empty (queue));
    DEBUG (9, g_assert (queue->balance == 0));

    /* Free the extra sections allocated during the last collection */
    i = 0;
    for (section = queue->free_list; section && i < GRAY_QUEUE_LENGTH_LIMIT - 1; section = section->next)
        i ++;
    if (!section)
        return;
    while (section->next) {
        next = section->next;
        section->next = next->next;
        gray_object_free_queue_section (next);
    }
}
Exemplo n.º 6
0
static inline char*
gray_object_dequeue (GrayQueue *queue)
{
    char *obj;

    if (gray_object_queue_is_empty (queue))
        return NULL;

    DEBUG (9, g_assert (queue->first->end));

    obj = queue->first->objects [--queue->first->end];

    if (G_UNLIKELY (queue->first->end == 0)) {
        GrayQueueSection *section = queue->first;
        queue->first = section->next;
        section->next = queue->free_list;
        queue->free_list = section;
    }

    DEBUG (9, --queue->balance);

    return obj;
}