static void workers_gray_queue_share_redirect (SgenGrayQueue *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_state.data.gc_in_progress) workers_wake_up_all (); return; } /* The stealable stack is empty, so fill it. */ mono_mutex_lock (&data->stealable_stack_mutex); while (data->stealable_stack_fill < STEALABLE_STACK_SIZE && (section = sgen_gray_object_dequeue_section (queue))) { int num = MIN (section->size, STEALABLE_STACK_SIZE - data->stealable_stack_fill); memcpy (data->stealable_stack + data->stealable_stack_fill, section->entries + section->size - num, sizeof (GrayQueueEntry) * num); section->size -= num; data->stealable_stack_fill += num; if (section->size) sgen_gray_object_enqueue_section (queue, section); else sgen_gray_object_free_queue_section (section); } if (sgen_gray_object_queue_is_empty (queue)) workers_steal (data, data, FALSE); mono_mutex_unlock (&data->stealable_stack_mutex); if (workers_state.data.gc_in_progress) workers_wake_up_all (); }
static gboolean workers_get_work (WorkerData *data) { SgenMajorCollector *major; g_assert (sgen_gray_object_queue_is_empty (&data->private_gray_queue)); /* If we're concurrent, steal from the workers distribute gray queue. */ major = sgen_get_major_collector (); if (major->is_concurrent) { GrayQueueSection *section = sgen_section_gray_queue_dequeue (&workers_distribute_gray_queue); if (section) { sgen_gray_object_enqueue_section (&data->private_gray_queue, section); return TRUE; } } /* Nobody to steal from */ g_assert (sgen_gray_object_queue_is_empty (&data->private_gray_queue)); return FALSE; }
static gboolean workers_get_work (WorkerData *data) { SgenMajorCollector *major; int i; g_assert (sgen_gray_object_queue_is_empty (&data->private_gray_queue)); /* Try to steal from our own stack. */ if (workers_steal (data, data, TRUE)) return TRUE; /* 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; } /* * If we're concurrent or parallel, from the workers * distribute gray queue. */ major = sgen_get_major_collector (); if (major->is_concurrent || major->is_parallel) { GrayQueueSection *section = sgen_section_gray_queue_dequeue (&workers_distribute_gray_queue); if (section) { sgen_gray_object_enqueue_section (&data->private_gray_queue, section); return TRUE; } } /* Nobody to steal from */ g_assert (sgen_gray_object_queue_is_empty (&data->private_gray_queue)); return FALSE; }