2 * This module contains the options managemente code of the garbage collector.
4 * Copyright: Copyright (C) 2010 Leandro Lucarella <http://www.llucax.com.ar/>
7 * License: Boost Software License - Version 1.0 - August 17th, 2003
9 * Permission is hereby granted, free of charge, to any person or organization
10 * obtaining a copy of the software and accompanying documentation covered by
11 * this license (the "Software") to use, reproduce, display, distribute,
12 * execute, and transmit the Software, and to prepare derivative works of the
13 * Software, and to permit third-parties to whom the Software is furnished to
14 * do so, all subject to the following:
16 * The copyright notices in the Software and this entire statement, including
17 * the above license grant, this restriction and the following disclaimer,
18 * must be included in all copies of the Software, in whole or in part, and
19 * all derivative works of the Software, unless such copies or derivative
20 * works are solely in the form of machine-executable object code generated by
21 * a source language processor.
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
26 * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
27 * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
28 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 * DEALINGS IN THE SOFTWARE.
31 * Authors: Leandro Lucarella
34 module rt.gc.cdgc.opts;
38 import cstdlib = tango.stdc.stdlib;
39 import cstring = tango.stdc.string;
40 import cerrno = tango.stdc.errno;
41 debug (PRINTF) import tango.stdc.stdio: printf;
47 const MAX_OPT_LEN = 256;
53 char[MAX_OPT_LEN] log_file = "";
54 char[MAX_OPT_LEN] malloc_stats_file = "";
55 char[MAX_OPT_LEN] collect_stats_file = "";
56 bool sentinel = false;
57 bool mem_stomp = false;
58 bool conservative = false;
60 bool eager_alloc = true;
61 uint min_free = 5; // percent of the heap (0-100)
62 size_t prealloc_psize = 0;
63 size_t prealloc_npools = 0;
66 package Options options;
72 int b(bool v) { return v; }
74 printf("rt.gc.cdgc.opts: verbose=%u, log_file='%s', "
75 "malloc_stats_file='%s', collect_stats_file='%s', sentinel=%d, "
76 "mem_stomp=%d, conservative=%d, fork=%d, eager_alloc=%d, "
77 "early_collect=%d, min_free=%u, prealloc_psize=%lu, "
78 "prealloc_npools=%lu\n", verbose, log_file.ptr,
79 malloc_stats_file.ptr, collect_stats_file.ptr, b(sentinel),
80 b(mem_stomp), b(conservative), b(fork), b(eager_alloc),
81 b(early_collect), min_free, prealloc_psize, prealloc_npools);
85 bool cstr_eq(char* s1, char* s2)
87 return cstring.strcmp(s1, s2) == 0;
91 bool parse_bool(char* value)
95 return (cstdlib.atoi(value) != 0);
99 void parse_prealloc(char* value)
103 long size = cstdlib.strtol(value, &end, 10);
104 if (end == value || cerrno.errno) // error parsing
106 size *= 1024 * 1024; // size is supposed to be in MiB
108 if (*end == 'x') { // number of pools specified
109 char* start = end + 1;
110 npools = cstdlib.strtol(start, &end, 10);
111 if (*end != '\0' || end == start || cerrno.errno) // error parsing
114 else if (*end != '\0') { // don't accept trailing garbage
117 if (size > 0 && npools > 0) {
118 options.prealloc_psize = size;
119 options.prealloc_npools = npools;
124 void parse_min_free(char* value)
127 long free = cstdlib.strtol(value, &end, 10);
128 if (*end != '\0' || end == value || cerrno.errno || free < 0 || free > 100)
130 options.min_free = free;
134 void process_option(char* opt_name, char* opt_value)
136 if (cstr_eq(opt_name, "verbose"))
137 options.verbose = cstdlib.atoi(opt_value);
138 else if (cstr_eq(opt_name, "log_file"))
139 cstring.strcpy(options.log_file.ptr, opt_value);
140 else if (cstr_eq(opt_name, "malloc_stats_file"))
141 cstring.strcpy(options.malloc_stats_file.ptr, opt_value);
142 else if (cstr_eq(opt_name, "collect_stats_file"))
143 cstring.strcpy(options.collect_stats_file.ptr, opt_value);
144 else if (cstr_eq(opt_name, "sentinel"))
145 options.sentinel = parse_bool(opt_value);
146 else if (cstr_eq(opt_name, "mem_stomp"))
147 options.mem_stomp = parse_bool(opt_value);
148 else if (cstr_eq(opt_name, "conservative"))
149 options.conservative = parse_bool(opt_value);
150 else if (cstr_eq(opt_name, "fork"))
151 options.fork = parse_bool(opt_value);
152 else if (cstr_eq(opt_name, "eager_alloc"))
153 options.eager_alloc = parse_bool(opt_value);
154 else if (cstr_eq(opt_name, "min_free"))
155 parse_min_free(opt_value);
156 else if (cstr_eq(opt_name, "pre_alloc"))
157 parse_prealloc(opt_value);
161 package void parse(char* opts_string)
163 char[MAX_OPT_LEN] opt_name;
165 char[MAX_OPT_LEN] opt_value;
167 char* curr = opt_name.ptr;
169 if (opts_string is null) {
170 debug (PRINTF) printf("rt.gc.cdgc.opts: no options overriden\n");
173 for (; *opts_string != '\0'; opts_string++)
175 char c = *opts_string;
176 if (i == MAX_OPT_LEN)
183 switch (*opts_string)
187 process_option(opt_name.ptr, opt_value.ptr);
195 curr = opt_value.ptr;
203 if (i == MAX_OPT_LEN)
206 process_option(opt_name.ptr, opt_value.ptr);
207 debug (PRINTF) print_options();
214 assert (verbose == 0);
215 assert (log_file[0] == '\0');
216 assert (sentinel == false);
217 assert (mem_stomp == false);
218 assert (conservative == false);
219 assert (fork == true);
220 assert (eager_alloc == true);
221 assert (prealloc_psize == 0);
222 assert (prealloc_npools == 0);
223 assert (min_free == 5);
227 assert (verbose == 0);
228 assert (log_file[0] == '\0');
229 assert (sentinel == false);
230 assert (mem_stomp == true);
231 assert (conservative == false);
232 assert (fork == true);
233 assert (eager_alloc == true);
234 assert (prealloc_psize == 0);
235 assert (prealloc_npools == 0);
236 assert (min_free == 5);
238 parse("mem_stomp=0:verbose=2:conservative:fork=0:eager_alloc=0");
240 assert (verbose == 2);
241 assert (log_file[0] == '\0');
242 assert (sentinel == false);
243 assert (mem_stomp == false);
244 assert (conservative == true);
245 assert (fork == false);
246 assert (eager_alloc == false);
247 assert (prealloc_psize == 0);
248 assert (prealloc_npools == 0);
249 assert (min_free == 5);
251 parse("log_file=12345 67890:verbose=1:sentinel=4:mem_stomp=1");
253 assert (verbose == 1);
254 assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
255 assert (sentinel == true);
256 assert (mem_stomp == true);
257 assert (conservative == true);
258 assert (fork == false);
259 assert (eager_alloc == false);
260 assert (prealloc_psize == 0);
261 assert (prealloc_npools == 0);
262 assert (min_free == 5);
264 parse("pre_alloc:min_free=30");
266 assert (verbose == 1);
267 assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
268 assert (sentinel == true);
269 assert (mem_stomp == true);
270 assert (conservative == true);
271 assert (fork == false);
272 assert (eager_alloc == false);
273 assert (prealloc_psize == 0);
274 assert (prealloc_npools == 0);
275 assert (min_free == 30);
277 parse("pre_alloc=1");
279 assert (verbose == 1);
280 assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
281 assert (sentinel == true);
282 assert (mem_stomp == true);
283 assert (conservative == true);
284 assert (fork == false);
285 assert (eager_alloc == false);
286 assert (prealloc_psize == 1 * 1024 * 1024);
287 assert (prealloc_npools == 1);
288 assert (min_free == 30);
290 parse("pre_alloc=5a:min_free=101");
292 assert (verbose == 1);
293 assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
294 assert (sentinel == true);
295 assert (mem_stomp == true);
296 assert (conservative == true);
297 assert (fork == false);
298 assert (eager_alloc == false);
299 assert (prealloc_psize == 1 * 1024 * 1024);
300 assert (prealloc_npools == 1);
301 assert (min_free == 30);
303 parse("pre_alloc=5x:min_free=-1");
305 assert (verbose == 1);
306 assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
307 assert (sentinel == true);
308 assert (mem_stomp == true);
309 assert (conservative == true);
310 assert (fork == false);
311 assert (eager_alloc == false);
312 assert (prealloc_psize == 1 * 1024 * 1024);
313 assert (prealloc_npools == 1);
314 assert (min_free == 30);
316 parse("pre_alloc=09x010:min_free=10a");
318 assert (verbose == 1);
319 assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
320 assert (sentinel == true);
321 assert (mem_stomp == true);
322 assert (conservative == true);
323 assert (fork == false);
324 assert (eager_alloc == false);
325 assert (prealloc_psize == 9 * 1024 * 1024);
326 assert (prealloc_npools == 10);
327 assert (min_free == 30);
329 parse("pre_alloc=5x2:min_free=1.0");
331 assert (verbose == 1);
332 assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
333 assert (sentinel == true);
334 assert (mem_stomp == true);
335 assert (conservative == true);
336 assert (fork == false);
337 assert (eager_alloc == false);
338 assert (prealloc_psize == 5 * 1024 * 1024);
339 assert (prealloc_npools == 2);
340 assert (min_free == 30);
342 parse("pre_alloc=9x5x:min_free=-1");
344 assert (verbose == 1);
345 assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
346 assert (sentinel == true);
347 assert (mem_stomp == true);
348 assert (conservative == true);
349 assert (fork == false);
350 assert (eager_alloc == false);
351 assert (prealloc_psize == 5 * 1024 * 1024);
352 assert (prealloc_npools == 2);
353 assert (min_free == 30);
355 parse("pre_alloc=9x-5:min_free=0");
357 assert (verbose == 1);
358 assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
359 assert (sentinel == true);
360 assert (mem_stomp == true);
361 assert (conservative == true);
362 assert (fork == false);
363 assert (eager_alloc == false);
364 assert (prealloc_psize == 5 * 1024 * 1024);
365 assert (prealloc_npools == 2);
366 assert (min_free == 0);
368 parse("pre_alloc=0x3x0x4:min_free=100");
370 assert (verbose == 1);
371 assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
372 assert (sentinel == true);
373 assert (mem_stomp == true);
374 assert (conservative == true);
375 assert (fork == false);
376 assert (eager_alloc == false);
377 assert (prealloc_psize == 5 * 1024 * 1024);
378 assert (prealloc_npools == 2);
379 assert (min_free == 100);
383 assert (verbose == 1);
384 assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
385 assert (sentinel == true);
386 assert (mem_stomp == true);
387 assert (conservative == true);
388 assert (fork == false);
389 assert (eager_alloc == false);
390 assert (prealloc_psize == 5 * 1024 * 1024);
391 assert (prealloc_npools == 2);
392 assert (min_free == 100);
396 assert (verbose == 1);
397 assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
398 assert (sentinel == true);
399 assert (mem_stomp == true);
400 assert (conservative == true);
401 assert (fork == false);
402 assert (eager_alloc == false);
403 assert (prealloc_psize == 5 * 1024 * 1024);
404 assert (prealloc_npools == 2);
405 assert (min_free == 100);
409 assert (verbose == 1);
410 assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
411 assert (sentinel == true);
412 assert (mem_stomp == true);
413 assert (conservative == true);
414 assert (fork == false);
415 assert (eager_alloc == false);
416 assert (prealloc_psize == 5 * 1024 * 1024);
417 assert (prealloc_npools == 2);
418 assert (min_free == 100);
422 assert (verbose == 1);
423 assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
424 assert (sentinel == true);
425 assert (mem_stomp == true);
426 assert (conservative == true);
427 assert (fork == false);
428 assert (eager_alloc == false);
429 assert (prealloc_psize == 5 * 1024 * 1024);
430 assert (prealloc_npools == 2);
431 assert (min_free == 100);
436 // vim: set et sw=4 sts=4 :