2 * sgen-gray.c: Gray queue management.
4 * Copyright 2001-2003 Ximian, Inc
5 * Copyright 2003-2010 Novell, Inc.
6 * Copyright (C) 2012 Xamarin Inc
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License 2.0 as published by the Free Software Foundation;
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License 2.0 along with this library; if not, write to the Free
19 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "metadata/sgen-gc.h"
25 #include "utils/mono-counters.h"
27 #define GRAY_QUEUE_LENGTH_LIMIT 64
30 sgen_gray_object_alloc_queue_section (SgenGrayQueue *queue)
32 GrayQueueSection *section;
34 if (queue->alloc_prepare_func)
35 queue->alloc_prepare_func (queue);
37 if (queue->free_list) {
38 /* Use the previously allocated queue sections if possible */
39 section = queue->free_list;
40 queue->free_list = section->next;
42 /* Allocate a new section */
43 section = sgen_alloc_internal (INTERNAL_MEM_GRAY_QUEUE);
48 /* Link it with the others */
49 section->next = queue->first;
50 queue->first = section;
54 sgen_gray_object_free_queue_section (GrayQueueSection *section)
56 sgen_free_internal (section, INTERNAL_MEM_GRAY_QUEUE);
60 * The following two functions are called in the inner loops of the
61 * collector, so they need to be as fast as possible. We have macros
62 * for them in sgen-gc.h.
66 sgen_gray_object_enqueue (SgenGrayQueue *queue, char *obj)
68 SGEN_ASSERT (9, obj, "enqueueing a null object");
69 //sgen_check_objref (obj);
70 if (G_UNLIKELY (!queue->first || queue->first->end == SGEN_GRAY_QUEUE_SECTION_SIZE))
71 sgen_gray_object_alloc_queue_section (queue);
72 SGEN_ASSERT (9, queue->first->end < SGEN_GRAY_QUEUE_SECTION_SIZE, "gray queue %p overflow, first %p, end %d", queue, queue->first, queue->first->end);
73 queue->first->objects [queue->first->end++] = obj;
75 SGEN_LOG_DO (9, ++queue->balance);
79 sgen_gray_object_dequeue (SgenGrayQueue *queue)
83 if (sgen_gray_object_queue_is_empty (queue))
86 SGEN_ASSERT (9, queue->first->end, "gray queue %p underflow, first %p, end %d", queue, queue->first, queue->first->end);
88 obj = queue->first->objects [--queue->first->end];
90 if (G_UNLIKELY (queue->first->end == 0)) {
91 GrayQueueSection *section = queue->first;
92 queue->first = section->next;
93 section->next = queue->free_list;
94 queue->free_list = section;
97 SGEN_LOG_DO (9, --queue->balance);
103 sgen_gray_object_dequeue_section (SgenGrayQueue *queue)
105 GrayQueueSection *section;
110 section = queue->first;
111 queue->first = section->next;
113 section->next = NULL;
119 sgen_gray_object_enqueue_section (SgenGrayQueue *queue, GrayQueueSection *section)
121 section->next = queue->first;
122 queue->first = section;
126 sgen_gray_object_queue_init (SgenGrayQueue *queue)
128 GrayQueueSection *section, *next;
131 g_assert (sgen_gray_object_queue_is_empty (queue));
132 SGEN_ASSERT (9, queue->balance == 0, "unbalanced queue on init %d", queue->balance);
134 /* Free the extra sections allocated during the last collection */
136 for (section = queue->free_list; section && i < GRAY_QUEUE_LENGTH_LIMIT - 1; section = section->next)
140 while (section->next) {
141 next = section->next;
142 section->next = next->next;
143 sgen_gray_object_free_queue_section (next);
148 sgen_gray_object_queue_init_with_alloc_prepare (SgenGrayQueue *queue, GrayQueueAllocPrepareFunc func, void *data)
150 sgen_gray_object_queue_init (queue);
151 queue->alloc_prepare_func = func;
152 queue->alloc_prepare_data = data;