2 * Copyright 2001-2003 Ximian, Inc
3 * Copyright 2003-2010 Novell, Inc.
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 #define GRAY_QUEUE_LENGTH_LIMIT 64
26 static GrayQueue gray_queue;
29 gray_object_alloc_queue_section (GrayQueue *queue)
31 GrayQueueSection *section;
33 if (queue->alloc_prepare_func)
34 queue->alloc_prepare_func (queue);
36 if (queue->free_list) {
37 /* Use the previously allocated queue sections if possible */
38 section = queue->free_list;
39 queue->free_list = section->next;
41 /* Allocate a new section */
42 section = mono_sgen_alloc_internal_fixed (queue->allocator, INTERNAL_MEM_GRAY_QUEUE);
47 /* Link it with the others */
48 section->next = queue->first;
49 queue->first = section;
53 gray_object_free_queue_section (GrayQueueSection *section, SgenInternalAllocator *thread_allocator)
55 mono_sgen_free_internal_delayed (section, INTERNAL_MEM_GRAY_QUEUE, thread_allocator);
58 static inline gboolean
59 gray_object_queue_is_empty (GrayQueue *queue)
61 return queue->first == NULL;
65 * The following two functions are called in the inner loops of the
66 * collector, so they need to be as fast as possible. We have macros
67 * for them in sgen-gc.h.
71 mono_sgen_gray_object_enqueue (GrayQueue *queue, char *obj)
73 DEBUG (9, g_assert (obj));
74 if (G_UNLIKELY (!queue->first || queue->first->end == SGEN_GRAY_QUEUE_SECTION_SIZE))
75 gray_object_alloc_queue_section (queue);
76 DEBUG (9, g_assert (queue->first && queue->first->end < SGEN_GRAY_QUEUE_SECTION_SIZE));
77 queue->first->objects [queue->first->end++] = obj;
79 DEBUG (9, ++queue->balance);
83 mono_sgen_gray_object_dequeue (GrayQueue *queue)
87 if (gray_object_queue_is_empty (queue))
90 DEBUG (9, g_assert (queue->first->end));
92 obj = queue->first->objects [--queue->first->end];
94 if (G_UNLIKELY (queue->first->end == 0)) {
95 GrayQueueSection *section = queue->first;
96 queue->first = section->next;
97 section->next = queue->free_list;
98 queue->free_list = section;
101 DEBUG (9, --queue->balance);
106 static GrayQueueSection*
107 gray_object_dequeue_section (GrayQueue *queue)
109 GrayQueueSection *section;
114 section = queue->first;
115 queue->first = section->next;
117 section->next = NULL;
123 gray_object_enqueue_section (GrayQueue *queue, GrayQueueSection *section)
125 section->next = queue->first;
126 queue->first = section;
130 gray_object_queue_init (GrayQueue *queue, SgenInternalAllocator *allocator)
132 GrayQueueSection *section, *next;
135 g_assert (gray_object_queue_is_empty (queue));
136 DEBUG (9, g_assert (queue->balance == 0));
138 queue->allocator = allocator;
140 /* Free the extra sections allocated during the last collection */
142 for (section = queue->free_list; section && i < GRAY_QUEUE_LENGTH_LIMIT - 1; section = section->next)
146 while (section->next) {
147 next = section->next;
148 section->next = next->next;
149 gray_object_free_queue_section (next, allocator);
154 gray_object_queue_init_with_alloc_prepare (GrayQueue *queue, SgenInternalAllocator *allocator, GrayQueueAllocPrepareFunc func, void *data)
156 gray_object_queue_init (queue, allocator);
157 queue->alloc_prepare_func = func;
158 queue->alloc_prepare_data = data;