Merge: doc: fixed some typos and other misc. corrections
[nit.git] / clib / gc_chooser.c
1 /* This file is part of NIT ( http://www.nitlanguage.org ).
2 *
3 * Copyright 2006-2009 Jean Privat <jean@pryen.org>
4 *
5 * This file is free software, which comes along with NIT. This software is
6 * distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
7 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
8 * PARTICULAR PURPOSE. You can modify it is you want, provided this header
9 * is kept unaltered, and a notification of the changes is added.
10 * You are allowed to redistribute it and sell it, alone or is a part of
11 * another product.
12 */
13
14 #include "gc_chooser.h"
15 #include <stdlib.h>
16 #include <string.h>
17
18 #ifdef ANDROID
19 #include <android/log.h>
20 #define PRINT_ERROR(...) ((void)__android_log_print(ANDROID_LOG_WARN, "nit", __VA_ARGS__))
21 #else
22 #define PRINT_ERROR(...) ((void)fprintf(stderr, __VA_ARGS__))
23 #endif
24
25 enum gc_option { gc_opt_large, gc_opt_malloc, gc_opt_boehm } gc_option;
26
27 #ifdef WITH_LIBGC
28 #include <gc.h>
29 #endif
30
31 void *nit_raw_alloc(size_t s0)
32 {
33 switch (gc_option) {
34 case gc_opt_malloc: return malloc(s0);
35 #ifdef WITH_LIBGC
36 case gc_opt_boehm: return GC_MALLOC_ATOMIC(s0);
37 #endif
38
39 default: return nit_alloc(s0);
40 }
41 }
42
43 static void *large_alloc(size_t s0)
44 {
45 static char * alloc_pos = NULL;
46 static size_t alloc_size = 0;
47 void * res;
48 size_t s = ((s0+3)/4)*4;
49 if(alloc_size < s) {
50 alloc_size = s + 1024*1024;
51 alloc_pos = (char *)calloc(alloc_size, 1);
52 }
53 res = alloc_pos;
54 alloc_size -= s;
55 alloc_pos += s;
56 return res;
57 }
58
59 void nit_gcollect(void) {
60 switch (gc_option) {
61 #ifdef WITH_LIBGC
62 case gc_opt_boehm: GC_gcollect(); break;
63 #endif
64 default: break; /* nothing can be done */
65 }
66 }
67
68 void *nit_alloc(size_t s0)
69 {
70 switch (gc_option) {
71 #ifdef WITH_LIBGC
72 case gc_opt_boehm: return GC_MALLOC(s0);
73 #endif
74 case gc_opt_malloc: return calloc(1, s0);
75 case gc_opt_large:
76 default: return large_alloc(s0);
77 }
78 }
79
80 void initialize_gc_option(void) {
81 /* GC default */
82 char *def;
83 #ifdef WITH_LIBGC
84 gc_option = gc_opt_boehm;
85 def = "boehm";
86 #else
87 gc_option = gc_opt_malloc;
88 def = "malloc";
89 #endif
90
91 /* Process GC runtime selection */
92 if (getenv("NIT_GC_OPTION") != NULL) {
93 char *opt=getenv("NIT_GC_OPTION");
94 if (strcmp(opt, "boehm")==0) {
95 #ifdef WITH_LIBGC
96 gc_option = gc_opt_boehm;
97 #else
98 PRINT_ERROR( "Compiled without Boehm GC support. Using default '%s'.\n", def);
99 #endif
100 } else if (strcmp(opt, "malloc")==0) {
101 gc_option = gc_opt_malloc;
102 } else if (strcmp(opt, "large")==0) {
103 gc_option = gc_opt_large;
104 } else if (strcmp(opt, "help")==0) {
105 PRINT_ERROR( "NIT_GC_OPTION accepts 'malloc', 'large'"
106 #ifdef WITH_LIBGC
107 ", 'boehm'"
108 #endif
109 ". Default is '%s'.\n", def);
110 exit(1);
111 } else {
112 PRINT_ERROR( "Invalid GC option in NIT_GC_OPTION environment variable. Using default '%s'.\n", def);
113 }
114 }
115
116 /* Initialize GC (if needed) */
117 switch(gc_option) {
118 #ifdef WITH_LIBGC
119 case gc_opt_boehm: GC_INIT(); break;
120 #endif
121 default: break; /* Nothing */
122 }
123 }
124
125 void gc_register_finalizer(void* obj) {
126 #ifdef WITH_LIBGC
127 GC_register_finalizer_no_order(obj, &gc_finalize, NULL, NULL, NULL);
128 #endif
129 }
130
131 void __attribute__((weak)) gc_finalize(void *obj, void* client_data) {}