]> git.llucax.com Git - software/dgc/cdgc.git/blob - rt/gc/cdgc/opts.d
Make realloc() a little more readable
[software/dgc/cdgc.git] / rt / gc / cdgc / opts.d
1 /**
2  * This module contains the options managemente code of the garbage collector.
3  *
4  * Copyright: Copyright (C) 2010 Leandro Lucarella <http://www.llucax.com.ar/>
5  *            All rights reserved.
6  *
7  * License: Boost Software License - Version 1.0 - August 17th, 2003
8  *
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:
15  *
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.
22  *
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.
30  *
31  * Authors: Leandro Lucarella
32  */
33
34 module rt.gc.cdgc.opts;
35
36 import cstdlib = tango.stdc.stdlib;
37 import cstring = tango.stdc.string;
38 import cerrno = tango.stdc.errno;
39
40
41 private:
42
43
44 const MAX_OPT_LEN = 256;
45
46
47 struct Options
48 {
49     uint verbose = 0;
50     char[MAX_OPT_LEN] log_file = "";
51     char[MAX_OPT_LEN] malloc_stats_file = "";
52     char[MAX_OPT_LEN] collect_stats_file = "";
53     bool sentinel = false;
54     bool mem_stomp = false;
55     bool conservative = false;
56     bool fork = true;
57     bool eager_alloc = true;
58     uint min_free = 15; // percent of the heap (0-100)
59     size_t prealloc_psize = 0;
60     size_t prealloc_npools = 0;
61 }
62
63 package Options options;
64
65
66 bool cstr_eq(char* s1, char* s2)
67 {
68     return cstring.strcmp(s1, s2) == 0;
69 }
70
71
72 bool parse_bool(char* value)
73 {
74     if (value[0] == '\0')
75         return true;
76     return (cstdlib.atoi(value) != 0);
77 }
78
79
80 void parse_prealloc(char* value)
81 {
82     char* end;
83     cerrno.errno = 0;
84     long size = cstdlib.strtol(value, &end, 10);
85     if (end == value || cerrno.errno) // error parsing
86         return;
87     size *= 1024 * 1024; // size is supposed to be in MiB
88     long npools = 1;
89     if (*end == 'x') { // number of pools specified
90         char* start = end + 1;
91         npools = cstdlib.strtol(start, &end, 10);
92         if (*end != '\0' || end == start || cerrno.errno) // error parsing
93             return;
94     }
95     else if (*end != '\0') { // don't accept trailing garbage
96         return;
97     }
98     if (size > 0 && npools > 0) {
99         options.prealloc_psize = size;
100         options.prealloc_npools = npools;
101     }
102 }
103
104
105 void parse_min_free(char* value)
106 {
107     char* end;
108     long free = cstdlib.strtol(value, &end, 10);
109     if (*end != '\0' || end == value || cerrno.errno || free < 0 || free > 100)
110         return;
111     options.min_free = free;
112 }
113
114
115 void process_option(char* opt_name, char* opt_value)
116 {
117     if (cstr_eq(opt_name, "verbose"))
118         options.verbose = cstdlib.atoi(opt_value);
119     else if (cstr_eq(opt_name, "log_file"))
120         cstring.strcpy(options.log_file.ptr, opt_value);
121     else if (cstr_eq(opt_name, "malloc_stats_file"))
122         cstring.strcpy(options.malloc_stats_file.ptr, opt_value);
123     else if (cstr_eq(opt_name, "collect_stats_file"))
124         cstring.strcpy(options.collect_stats_file.ptr, opt_value);
125     else if (cstr_eq(opt_name, "sentinel"))
126         options.sentinel = parse_bool(opt_value);
127     else if (cstr_eq(opt_name, "mem_stomp"))
128         options.mem_stomp = parse_bool(opt_value);
129     else if (cstr_eq(opt_name, "conservative"))
130         options.conservative = parse_bool(opt_value);
131     else if (cstr_eq(opt_name, "fork"))
132         options.fork = parse_bool(opt_value);
133     else if (cstr_eq(opt_name, "eager_alloc"))
134         options.eager_alloc = parse_bool(opt_value);
135     else if (cstr_eq(opt_name, "min_free"))
136         parse_min_free(opt_value);
137     else if (cstr_eq(opt_name, "pre_alloc"))
138         parse_prealloc(opt_value);
139 }
140
141
142 package void parse(char* opts_string)
143 {
144     char[MAX_OPT_LEN] opt_name;
145     opt_name[0] = '\0';
146     char[MAX_OPT_LEN] opt_value;
147     opt_value[0] = '\0';
148     char* curr = opt_name.ptr;
149     size_t i = 0;
150     if (opts_string is null)
151         return;
152     for (; *opts_string != '\0'; opts_string++)
153     {
154         char c = *opts_string;
155         if (i == MAX_OPT_LEN)
156         {
157             if (c != ':')
158                 continue;
159             else
160                 i--;
161         }
162         switch (*opts_string)
163         {
164         case ':':
165             curr[i] = '\0';
166             process_option(opt_name.ptr, opt_value.ptr);
167             i = 0;
168             opt_name[0] = '\0';
169             opt_value[0] = '\0';
170             curr = opt_name.ptr;
171             break;
172         case '=':
173             opt_name[i] = '\0';
174             curr = opt_value.ptr;
175             i = 0;
176             break;
177         default:
178             curr[i] = c;
179             ++i;
180         }
181     }
182     if (i == MAX_OPT_LEN)
183         i--;
184     curr[i] = '\0';
185     process_option(opt_name.ptr, opt_value.ptr);
186 }
187
188
189 unittest
190 {
191     with (options) {
192         assert (verbose == 0);
193         assert (log_file[0] == '\0');
194         assert (sentinel == false);
195         assert (mem_stomp == false);
196         assert (conservative == false);
197         assert (fork == true);
198         assert (eager_alloc == true);
199         assert (prealloc_psize == 0);
200         assert (prealloc_npools == 0);
201         assert (min_free == 15);
202     }
203     parse("mem_stomp");
204     with (options) {
205         assert (verbose == 0);
206         assert (log_file[0] == '\0');
207         assert (sentinel == false);
208         assert (mem_stomp == true);
209         assert (conservative == false);
210         assert (fork == true);
211         assert (eager_alloc == true);
212         assert (prealloc_psize == 0);
213         assert (prealloc_npools == 0);
214         assert (min_free == 15);
215     }
216     parse("mem_stomp=0:verbose=2:conservative:fork=0:eager_alloc=0");
217     with (options) {
218         assert (verbose == 2);
219         assert (log_file[0] == '\0');
220         assert (sentinel == false);
221         assert (mem_stomp == false);
222         assert (conservative == true);
223         assert (fork == false);
224         assert (eager_alloc == false);
225         assert (prealloc_psize == 0);
226         assert (prealloc_npools == 0);
227         assert (min_free == 15);
228     }
229     parse("log_file=12345 67890:verbose=1:sentinel=4:mem_stomp=1");
230     with (options) {
231         assert (verbose == 1);
232         assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
233         assert (sentinel == true);
234         assert (mem_stomp == true);
235         assert (conservative == true);
236         assert (fork == false);
237         assert (eager_alloc == false);
238         assert (prealloc_psize == 0);
239         assert (prealloc_npools == 0);
240     }
241     parse("pre_alloc:min_free=30");
242     with (options) {
243         assert (verbose == 1);
244         assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
245         assert (sentinel == true);
246         assert (mem_stomp == true);
247         assert (conservative == true);
248         assert (fork == false);
249         assert (eager_alloc == false);
250         assert (prealloc_psize == 0);
251         assert (prealloc_npools == 0);
252         assert (min_free == 30);
253     }
254     parse("pre_alloc=1");
255     with (options) {
256         assert (verbose == 1);
257         assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
258         assert (sentinel == true);
259         assert (mem_stomp == true);
260         assert (conservative == true);
261         assert (fork == false);
262         assert (eager_alloc == false);
263         assert (prealloc_psize == 1 * 1024 * 1024);
264         assert (prealloc_npools == 1);
265         assert (min_free == 30);
266     }
267     parse("pre_alloc=5a:min_free=101");
268     with (options) {
269         assert (verbose == 1);
270         assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
271         assert (sentinel == true);
272         assert (mem_stomp == true);
273         assert (conservative == true);
274         assert (fork == false);
275         assert (eager_alloc == false);
276         assert (prealloc_psize == 1 * 1024 * 1024);
277         assert (prealloc_npools == 1);
278         assert (min_free == 30);
279     }
280     parse("pre_alloc=5x:min_free=-1");
281     with (options) {
282         assert (verbose == 1);
283         assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
284         assert (sentinel == true);
285         assert (mem_stomp == true);
286         assert (conservative == true);
287         assert (fork == false);
288         assert (eager_alloc == false);
289         assert (prealloc_psize == 1 * 1024 * 1024);
290         assert (prealloc_npools == 1);
291         assert (min_free == 30);
292     }
293     parse("pre_alloc=09x010:min_free=10a");
294     with (options) {
295         assert (verbose == 1);
296         assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
297         assert (sentinel == true);
298         assert (mem_stomp == true);
299         assert (conservative == true);
300         assert (fork == false);
301         assert (eager_alloc == false);
302         assert (prealloc_psize == 9 * 1024 * 1024);
303         assert (prealloc_npools == 10);
304         assert (min_free == 30);
305     }
306     parse("pre_alloc=5x2:min_free=1.0");
307     with (options) {
308         assert (verbose == 1);
309         assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
310         assert (sentinel == true);
311         assert (mem_stomp == true);
312         assert (conservative == true);
313         assert (fork == false);
314         assert (eager_alloc == false);
315         assert (prealloc_psize == 5 * 1024 * 1024);
316         assert (prealloc_npools == 2);
317         assert (min_free == 30);
318     }
319     parse("pre_alloc=9x5x:min_free=-1");
320     with (options) {
321         assert (verbose == 1);
322         assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
323         assert (sentinel == true);
324         assert (mem_stomp == true);
325         assert (conservative == true);
326         assert (fork == false);
327         assert (eager_alloc == false);
328         assert (prealloc_psize == 5 * 1024 * 1024);
329         assert (prealloc_npools == 2);
330         assert (min_free == 30);
331     }
332     parse("pre_alloc=9x-5:min_free=0");
333     with (options) {
334         assert (verbose == 1);
335         assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
336         assert (sentinel == true);
337         assert (mem_stomp == true);
338         assert (conservative == true);
339         assert (fork == false);
340         assert (eager_alloc == false);
341         assert (prealloc_psize == 5 * 1024 * 1024);
342         assert (prealloc_npools == 2);
343         assert (min_free == 0);
344     }
345     parse("pre_alloc=0x3x0x4:min_free=100");
346     with (options) {
347         assert (verbose == 1);
348         assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
349         assert (sentinel == true);
350         assert (mem_stomp == true);
351         assert (conservative == true);
352         assert (fork == false);
353         assert (eager_alloc == false);
354         assert (prealloc_psize == 5 * 1024 * 1024);
355         assert (prealloc_npools == 2);
356         assert (min_free == 100);
357     }
358     parse(null);
359     with (options) {
360         assert (verbose == 1);
361         assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
362         assert (sentinel == true);
363         assert (mem_stomp == true);
364         assert (conservative == true);
365         assert (fork == false);
366         assert (eager_alloc == false);
367         assert (prealloc_psize == 5 * 1024 * 1024);
368         assert (prealloc_npools == 2);
369         assert (min_free == 100);
370     }
371     parse("");
372     with (options) {
373         assert (verbose == 1);
374         assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
375         assert (sentinel == true);
376         assert (mem_stomp == true);
377         assert (conservative == true);
378         assert (fork == false);
379         assert (eager_alloc == false);
380         assert (prealloc_psize == 5 * 1024 * 1024);
381         assert (prealloc_npools == 2);
382         assert (min_free == 100);
383     }
384     parse(":");
385     with (options) {
386         assert (verbose == 1);
387         assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
388         assert (sentinel == true);
389         assert (mem_stomp == true);
390         assert (conservative == true);
391         assert (fork == false);
392         assert (eager_alloc == false);
393         assert (prealloc_psize == 5 * 1024 * 1024);
394         assert (prealloc_npools == 2);
395         assert (min_free == 100);
396     }
397     parse("::::");
398     with (options) {
399         assert (verbose == 1);
400         assert (cstring.strcmp(log_file.ptr, "12345 67890".ptr) == 0);
401         assert (sentinel == true);
402         assert (mem_stomp == true);
403         assert (conservative == true);
404         assert (fork == false);
405         assert (eager_alloc == false);
406         assert (prealloc_psize == 5 * 1024 * 1024);
407         assert (prealloc_npools == 2);
408         assert (min_free == 100);
409     }
410 }
411
412
413 // vim: set et sw=4 sts=4 :