void sgen_gray_object_enqueue (SgenGrayQueue *queue, GCObject *obj, SgenDescriptor desc) { GrayQueueEntry entry = SGEN_GRAY_QUEUE_ENTRY (obj, desc); HEAVY_STAT (stat_gray_queue_enqueue_slow_path ++); SGEN_ASSERT (9, obj, "enqueueing a null object"); //sgen_check_objref (obj); #ifdef SGEN_CHECK_GRAY_OBJECT_ENQUEUE if (queue->enqueue_check_func) queue->enqueue_check_func (obj); #endif if (G_UNLIKELY (!queue->first || queue->cursor == GRAY_LAST_CURSOR_POSITION (queue->first))) { if (queue->first) { /* Set the current section size back to default, might have been changed by sgen_gray_object_dequeue_section */ queue->first->size = SGEN_GRAY_QUEUE_SECTION_SIZE; } sgen_gray_object_alloc_queue_section (queue); } STATE_ASSERT (queue->first, GRAY_QUEUE_SECTION_STATE_ENQUEUED); SGEN_ASSERT (9, queue->cursor <= GRAY_LAST_CURSOR_POSITION (queue->first), "gray queue %p overflow, first %p, cursor %p", queue, queue->first, queue->cursor); *++queue->cursor = entry; #ifdef SGEN_HEAVY_BINARY_PROTOCOL binary_protocol_gray_enqueue (queue, queue->cursor, obj); #endif }
void sgen_gray_object_enqueue (SgenGrayQueue *queue, GCObject *obj, SgenDescriptor desc, gboolean is_parallel) { GrayQueueEntry entry = SGEN_GRAY_QUEUE_ENTRY (obj, desc); HEAVY_STAT (stat_gray_queue_enqueue_slow_path ++); SGEN_ASSERT (9, obj, "enqueueing a null object"); //sgen_check_objref (obj); #ifdef SGEN_CHECK_GRAY_OBJECT_ENQUEUE if (queue->enqueue_check_func) queue->enqueue_check_func (obj); #endif if (G_UNLIKELY (!queue->first || queue->cursor == GRAY_LAST_CURSOR_POSITION (queue->first))) { if (queue->first) { /* * We don't actively update the section size with each push/pop. For the first * section we determine the size from the cursor position. For the reset of the * sections we need to have the size set. */ queue->first->size = SGEN_GRAY_QUEUE_SECTION_SIZE; } sgen_gray_object_alloc_queue_section (queue, is_parallel); } STATE_ASSERT (queue->first, GRAY_QUEUE_SECTION_STATE_ENQUEUED); SGEN_ASSERT (9, queue->cursor <= GRAY_LAST_CURSOR_POSITION (queue->first), "gray queue %p overflow, first %p, cursor %p", queue, queue->first, queue->cursor); *++queue->cursor = entry; #ifdef SGEN_HEAVY_BINARY_PROTOCOL binary_protocol_gray_enqueue (queue, queue->cursor, obj); #endif }
GrayQueueEntry sgen_gray_object_dequeue (SgenGrayQueue *queue) { GrayQueueEntry entry; HEAVY_STAT (stat_gray_queue_dequeue_slow_path ++); if (sgen_gray_object_queue_is_empty (queue)) { entry.obj = NULL; return entry; } STATE_ASSERT (queue->first, GRAY_QUEUE_SECTION_STATE_ENQUEUED); SGEN_ASSERT (9, queue->cursor >= GRAY_FIRST_CURSOR_POSITION (queue->first), "gray queue %p underflow", queue); entry = *queue->cursor--; #ifdef SGEN_HEAVY_BINARY_PROTOCOL binary_protocol_gray_dequeue (queue, queue->cursor + 1, entry.obj); #endif if (G_UNLIKELY (queue->cursor < GRAY_FIRST_CURSOR_POSITION (queue->first))) { GrayQueueSection *section = queue->first; queue->first = section->next; section->next = queue->free_list; STATE_TRANSITION (section, GRAY_QUEUE_SECTION_STATE_ENQUEUED, GRAY_QUEUE_SECTION_STATE_FREE_LIST); queue->free_list = section; queue->cursor = queue->first ? queue->first->entries + queue->first->size - 1 : NULL; } return entry; }
GrayQueueEntry sgen_gray_object_dequeue (SgenGrayQueue *queue, gboolean is_parallel) { GrayQueueEntry entry; HEAVY_STAT (stat_gray_queue_dequeue_slow_path ++); if (sgen_gray_object_queue_is_empty (queue)) { entry.obj = NULL; return entry; } STATE_ASSERT (queue->first, GRAY_QUEUE_SECTION_STATE_ENQUEUED); SGEN_ASSERT (9, queue->cursor >= GRAY_FIRST_CURSOR_POSITION (queue->first), "gray queue %p underflow", queue); entry = *queue->cursor--; #ifdef SGEN_HEAVY_BINARY_PROTOCOL binary_protocol_gray_dequeue (queue, queue->cursor + 1, entry.obj); #endif if (G_UNLIKELY (queue->cursor < GRAY_FIRST_CURSOR_POSITION (queue->first))) { GrayQueueSection *section; gint32 old_num_sections = 0; if (is_parallel) old_num_sections = mono_atomic_dec_i32 (&queue->num_sections); else queue->num_sections--; if (is_parallel && old_num_sections <= 0) { mono_os_mutex_lock (&queue->steal_mutex); } section = queue->first; queue->first = section->next; if (queue->first) { queue->first->prev = NULL; } else { queue->last = NULL; SGEN_ASSERT (0, !old_num_sections, "Why do we have an inconsistent number of sections ?"); } section->next = queue->free_list; STATE_TRANSITION (section, GRAY_QUEUE_SECTION_STATE_ENQUEUED, GRAY_QUEUE_SECTION_STATE_FREE_LIST); queue->free_list = section; queue->cursor = queue->first ? queue->first->entries + queue->first->size - 1 : NULL; if (is_parallel && old_num_sections <= 0) { mono_os_mutex_unlock (&queue->steal_mutex); } } return entry; }
void sgen_gray_object_queue_trim_free_list (SgenGrayQueue *queue) { GrayQueueSection *section, *next; int i = 0; for (section = queue->free_list; section && i < GRAY_QUEUE_LENGTH_LIMIT - 1; section = section->next) { STATE_ASSERT (section, GRAY_QUEUE_SECTION_STATE_FREE_LIST); i ++; } if (!section) return; while (section->next) { next = section->next; section->next = next->next; STATE_TRANSITION (next, GRAY_QUEUE_SECTION_STATE_FREE_LIST, GRAY_QUEUE_SECTION_STATE_FLOATING); sgen_gray_object_free_queue_section (next); } }