Merge pull request #409 from Alkarex/patch-1
[mono.git] / mono / metadata / sgen-internal.c
1 /*
2  * sgen-internal.c
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sublicense, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  * 
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  * 
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23
24 #include "config.h"
25
26 #ifdef HAVE_SGEN_GC
27
28 #include "utils/mono-counters.h"
29 #include "metadata/sgen-gc.h"
30 #include "utils/lock-free-alloc.h"
31 #include "metadata/sgen-memory-governor.h"
32
33 /* keep each size a multiple of ALLOC_ALIGN */
34 static const int allocator_sizes [] = {
35            8,   16,   24,   32,   40,   48,   64,   80,
36           96,  128,  160,  192,  224,  248,  320,  384,
37          448,  528,  584,  680,  816, 1088, 1360, 2040,
38         2336, 2728, 3272, 4088, 5456, 8184 };
39
40 #define NUM_ALLOCATORS  (sizeof (allocator_sizes) / sizeof (int))
41
42 static MonoLockFreeAllocSizeClass size_classes [NUM_ALLOCATORS];
43 static MonoLockFreeAllocator allocators [NUM_ALLOCATORS];
44
45 /*
46  * Find the allocator index for memory chunks that can contain @size
47  * objects.
48  */
49 static int
50 index_for_size (size_t size)
51 {
52         int slot;
53         /* do a binary search or lookup table later. */
54         for (slot = 0; slot < NUM_ALLOCATORS; ++slot) {
55                 if (allocator_sizes [slot] >= size)
56                         return slot;
57         }
58         g_assert_not_reached ();
59         return -1;
60 }
61
62 /*
63  * Allocator indexes for the fixed INTERNAL_MEM_XXX types.  -1 if that
64  * type is dynamic.
65  */
66 static int fixed_type_allocator_indexes [INTERNAL_MEM_MAX];
67
68 void
69 sgen_register_fixed_internal_mem_type (int type, size_t size)
70 {
71         int slot;
72
73         g_assert (type >= 0 && type < INTERNAL_MEM_MAX);
74
75         slot = index_for_size (size);
76         g_assert (slot >= 0);
77
78         if (fixed_type_allocator_indexes [type] == -1)
79                 fixed_type_allocator_indexes [type] = slot;
80         else
81                 g_assert (fixed_type_allocator_indexes [type] == slot);
82 }
83
84 static const char*
85 description_for_type (int type)
86 {
87         switch (type) {
88         case INTERNAL_MEM_PIN_QUEUE: return "pin-queue";
89         case INTERNAL_MEM_FRAGMENT: return "fragment";
90         case INTERNAL_MEM_SECTION: return "section";
91         case INTERNAL_MEM_SCAN_STARTS: return "scan-starts";
92         case INTERNAL_MEM_FIN_TABLE: return "fin-table";
93         case INTERNAL_MEM_FINALIZE_ENTRY: return "finalize-entry";
94         case INTERNAL_MEM_FINALIZE_READY_ENTRY: return "finalize-ready-entry";
95         case INTERNAL_MEM_DISLINK_TABLE: return "dislink-table";
96         case INTERNAL_MEM_DISLINK: return "dislink";
97         case INTERNAL_MEM_ROOTS_TABLE: return "roots-table";
98         case INTERNAL_MEM_ROOT_RECORD: return "root-record";
99         case INTERNAL_MEM_STATISTICS: return "statistics";
100         case INTERNAL_MEM_STAT_PINNED_CLASS: return "pinned-class";
101         case INTERNAL_MEM_STAT_REMSET_CLASS: return "remset-class";
102         case INTERNAL_MEM_REMSET: return "remset";
103         case INTERNAL_MEM_GRAY_QUEUE: return "gray-queue";
104         case INTERNAL_MEM_STORE_REMSET: return "store-remset";
105         case INTERNAL_MEM_MS_TABLES: return "marksweep-tables";
106         case INTERNAL_MEM_MS_BLOCK_INFO: return "marksweep-block-info";
107         case INTERNAL_MEM_EPHEMERON_LINK: return "ephemeron-link";
108         case INTERNAL_MEM_WORKER_DATA: return "worker-data";
109         case INTERNAL_MEM_BRIDGE_DATA: return "bridge-data";
110         case INTERNAL_MEM_BRIDGE_HASH_TABLE: return "bridge-hash-table";
111         case INTERNAL_MEM_BRIDGE_HASH_TABLE_ENTRY: return "bridge-hash-table-entry";
112         case INTERNAL_MEM_BRIDGE_ALIVE_HASH_TABLE: return "bridge-alive-hash-table";
113         case INTERNAL_MEM_BRIDGE_ALIVE_HASH_TABLE_ENTRY: return "bridge-alive-hash-table-entry";
114         case INTERNAL_MEM_JOB_QUEUE_ENTRY: return "job-queue-entry";
115         case INTERNAL_MEM_TOGGLEREF_DATA: return "toggleref-data";
116         default:
117                 g_assert_not_reached ();
118         }
119 }
120
121 void*
122 sgen_alloc_internal_dynamic (size_t size, int type, gboolean assert_on_failure)
123 {
124         int index;
125         void *p;
126
127         if (size > allocator_sizes [NUM_ALLOCATORS - 1]) {
128                 p = sgen_alloc_os_memory (size, SGEN_ALLOC_INTERNAL | SGEN_ALLOC_ACTIVATE, NULL);
129                 if (!p)
130                         sgen_assert_memory_alloc (NULL, description_for_type (type));
131                 return p;
132         }
133
134         index = index_for_size (size);
135
136         p = mono_lock_free_alloc (&allocators [index]);
137         if (!p)
138                 sgen_assert_memory_alloc (NULL, description_for_type (type));
139         memset (p, 0, size);
140         return p;
141 }
142
143 void
144 sgen_free_internal_dynamic (void *addr, size_t size, int type)
145 {
146         if (!addr)
147                 return;
148
149         if (size > allocator_sizes [NUM_ALLOCATORS - 1]) {
150                 sgen_free_os_memory (addr, size, SGEN_ALLOC_INTERNAL);
151                 return;
152         }
153
154         mono_lock_free_free (addr);
155 }
156
157 void*
158 sgen_alloc_internal (int type)
159 {
160         int index = fixed_type_allocator_indexes [type];
161         void *p;
162         g_assert (index >= 0 && index < NUM_ALLOCATORS);
163         p = mono_lock_free_alloc (&allocators [index]);
164         memset (p, 0, allocator_sizes [index]);
165         return p;
166 }
167
168 void
169 sgen_free_internal (void *addr, int type)
170 {
171         int index;
172
173         if (!addr)
174                 return;
175
176         index = fixed_type_allocator_indexes [type];
177         g_assert (index >= 0 && index < NUM_ALLOCATORS);
178
179         mono_lock_free_free (addr);
180 }
181
182 void
183 sgen_dump_internal_mem_usage (FILE *heap_dump_file)
184 {
185         /*
186         int i;
187
188         fprintf (heap_dump_file, "<other-mem-usage type=\"large-internal\" size=\"%lld\"/>\n", large_internal_bytes_alloced);
189         fprintf (heap_dump_file, "<other-mem-usage type=\"pinned-chunks\" size=\"%lld\"/>\n", pinned_chunk_bytes_alloced);
190         for (i = 0; i < INTERNAL_MEM_MAX; ++i) {
191                 fprintf (heap_dump_file, "<other-mem-usage type=\"%s\" size=\"%ld\"/>\n",
192                                 description_for_type (i), unmanaged_allocator.small_internal_mem_bytes [i]);
193         }
194         */
195 }
196
197 void
198 sgen_report_internal_mem_usage (void)
199 {
200         /* FIXME: implement */
201         printf ("not implemented yet\n");
202 }
203
204 void
205 sgen_init_internal_allocator (void)
206 {
207         int i;
208
209         for (i = 0; i < INTERNAL_MEM_MAX; ++i)
210                 fixed_type_allocator_indexes [i] = -1;
211
212         for (i = 0; i < NUM_ALLOCATORS; ++i) {
213                 mono_lock_free_allocator_init_size_class (&size_classes [i], allocator_sizes [i]);
214                 mono_lock_free_allocator_init_allocator (&allocators [i], &size_classes [i]);
215         }
216 }
217
218 #endif