2009-12-16 Rodrigo Kumpera <rkumpera@novell.com>
[mono.git] / mono / metadata / sgen-gray.c
1 #define GRAY_QUEUE_SECTION_SIZE 125
2 #define GRAY_QUEUE_LENGTH_LIMIT 64
3
4 typedef struct _GrayQueueSection GrayQueueSection;
5 struct _GrayQueueSection {
6         int start;
7         int end;
8         GrayQueueSection *next;
9         char *objects [GRAY_QUEUE_SECTION_SIZE];
10 };
11
12 static GrayQueueSection *gray_queue_start = NULL;
13 static GrayQueueSection *gray_queue_end = NULL;
14
15 static GrayQueueSection *gray_queue_section_free_list = NULL;
16 static int gray_queue_free_list_length = 0;
17
18 static int gray_queue_balance = 0;
19 static int num_gray_queue_sections = 0;
20
21 static void
22 gray_object_alloc_queue_section (void)
23 {
24         GrayQueueSection *section;
25
26         if (gray_queue_section_free_list) {
27                 section = gray_queue_section_free_list;
28                 gray_queue_section_free_list = gray_queue_section_free_list->next;
29                 --gray_queue_free_list_length;
30         } else {
31                 section = get_internal_mem (sizeof (GrayQueueSection), INTERNAL_MEM_GRAY_QUEUE);
32                 ++num_gray_queue_sections;
33         }
34
35         section->start = section->end = 0;
36         section->next = NULL;
37
38         if (gray_queue_end) {
39                 g_assert (gray_queue_start);
40                 gray_queue_end = gray_queue_end->next = section;
41         } else {
42                 g_assert (!gray_queue_start);
43                 gray_queue_start = gray_queue_end = section;
44         }
45 }
46
47 static void
48 gray_object_enqueue (char *obj)
49 {
50         g_assert (obj);
51         if (!gray_queue_end || gray_queue_end->end == GRAY_QUEUE_SECTION_SIZE)
52                 gray_object_alloc_queue_section ();
53         g_assert (gray_queue_end && gray_queue_end->end < GRAY_QUEUE_SECTION_SIZE);
54         gray_queue_end->objects [gray_queue_end->end++] = obj;
55
56         ++gray_queue_balance;
57 }
58
59 static gboolean
60 gray_object_queue_is_empty (void)
61 {
62         if (!gray_queue_start) {
63                 g_assert (!gray_queue_end);
64                 return TRUE;
65         } else {
66                 g_assert (gray_queue_end);
67                 return FALSE;
68         }
69 }
70
71 static char*
72 gray_object_dequeue (void)
73 {
74         char *obj;
75
76         if (gray_object_queue_is_empty ())
77                 return NULL;
78
79         g_assert (gray_queue_start->start < gray_queue_start->end);
80
81         obj = gray_queue_start->objects [gray_queue_start->start++];
82
83         if (gray_queue_start->start == gray_queue_start->end) {
84                 GrayQueueSection *section = gray_queue_start->next;
85                 if (gray_queue_free_list_length >= GRAY_QUEUE_LENGTH_LIMIT) {
86                         free_internal_mem (gray_queue_start, INTERNAL_MEM_GRAY_QUEUE);
87                 } else {
88                         gray_queue_start->next = gray_queue_section_free_list;
89                         gray_queue_section_free_list = gray_queue_start;
90                         ++gray_queue_free_list_length;
91                 }
92                 if (section)
93                         gray_queue_start = section;
94                 else
95                         gray_queue_start = gray_queue_end = NULL;
96         }
97
98         --gray_queue_balance;
99
100         return obj;
101 }
102
103 static void
104 gray_object_queue_init (void)
105 {
106         g_assert (gray_object_queue_is_empty ());
107         g_assert (sizeof (GrayQueueSection) < MAX_FREELIST_SIZE);
108         g_assert (gray_queue_balance == 0);
109 }