Include options.h instead of main.h
[cacao.git] / src / mm / boehm.c
1 /* mm/boehm.c - interface for boehm gc
2
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4    R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5    M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6    P. Tomsich, J. Wenninger
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Stefan Ring
28
29    $Id: boehm.c 1226 2004-06-30 19:26:39Z twisti $
30
31 */
32
33 #if defined(USE_THREADS) && defined(NATIVE_THREADS) && defined(__LINUX__)
34 #define GC_LINUX_THREADS
35 #endif
36
37 #include "options.h"
38 #include "boehm.h"
39 #include "global.h"
40 #include "native.h"
41 #include "asmpart.h"
42 #include "builtin.h"
43 #include "threads/thread.h"
44 #include "toolbox/logging.h"
45 #include "boehm-gc/include/gc.h"
46
47
48 static bool in_gc_out_of_memory = false;    /* is GC out of memory?           */
49
50
51 static void *stackcall_twoargs(struct otherstackcall *p)
52 {
53         return (*p->p2)(p->p, p->l);
54 }
55
56
57 static void *stackcall_malloc(void *p, u4 bytelength)
58 {
59         return GC_MALLOC(bytelength);
60 }
61
62
63 static void *stackcall_malloc_atomic(void *p, u4 bytelength)
64 {
65         return GC_MALLOC_ATOMIC(bytelength);
66 }
67
68
69 static void *stackcall_malloc_uncollectable(void *p, u4 bytelength)
70 {
71         return GC_MALLOC_UNCOLLECTABLE(bytelength);
72 }
73
74
75 static void *stackcall_realloc(void *p, u4 bytelength)
76 {
77         return GC_REALLOC(p, bytelength);
78 }
79
80 static void *stackcall_free(void *p, u4 bytelength)
81 {
82         GC_FREE(p);
83         return NULL;
84 }
85
86
87 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
88 #define MAINTHREADCALL(r,m,pp,ll) \
89         if (currentThread == NULL || currentThread == mainThread) { \
90                 r = m(pp, ll); \
91         } else { \
92                 struct otherstackcall sc; \
93                 sc.p2 = m; \
94                 sc.p = pp; \
95                 sc.l = ll; \
96                 r = (*asm_switchstackandcall)(CONTEXT(mainThread).usedStackTop, \
97                                 stackcall_twoargs, \
98                                 (void**)&(CONTEXT(currentThread).usedStackTop), &sc); \
99         }
100 #else
101 #define MAINTHREADCALL(r,m,pp,ll) \
102         { r = m(pp, ll); }
103 #endif
104
105
106 void *heap_alloc_uncollectable(u4 bytelength)
107 {
108         void *result;
109         MAINTHREADCALL(result, stackcall_malloc_uncollectable, NULL, bytelength);
110         return result;
111 }
112
113
114 void runboehmfinalizer(void *o, void *p)
115 {
116         java_objectheader *ob = (java_objectheader *) o;
117
118         asm_calljavafunction(ob->vftbl->class->finalizer, ob, NULL, NULL, NULL);
119         
120         /* if we had an exception in the finalizer, ignore it */
121         *exceptionptr = NULL;
122 }
123
124
125 void *heap_allocate(u4 bytelength, bool references, methodinfo *finalizer)
126 {
127         void *result;
128
129         if (references) {
130                 MAINTHREADCALL(result, stackcall_malloc, NULL, bytelength);
131
132         } else {
133                 MAINTHREADCALL(result, stackcall_malloc_atomic, NULL, bytelength);
134         }
135
136         if (!result) {
137                 return NULL;
138         }
139
140         if (finalizer)
141                 GC_REGISTER_FINALIZER(result, runboehmfinalizer, 0, 0, 0);
142
143         return (u1*) result;
144 }
145
146
147 void *heap_reallocate(void *p, u4 bytelength)
148 {
149         void *result;
150
151         MAINTHREADCALL(result, stackcall_realloc, p, bytelength);
152
153         return result;
154 }
155
156 void heap_free(void *p)
157 {
158         void *result;
159
160         MAINTHREADCALL(result, stackcall_free, p, 0);
161 }
162
163
164 void gc_init(u4 heapmaxsize, u4 heapstartsize)
165 {
166         size_t heapcurrentsize;
167
168         GC_init();
169
170         /* set the maximal heap size */
171         GC_set_max_heap_size(heapmaxsize);
172
173         /* set the initial heap size */
174         heapcurrentsize = GC_get_heap_size();
175         if (heapstartsize > heapcurrentsize) {
176                 GC_expand_hp(heapstartsize - heapcurrentsize);
177         }
178
179         /* define OOM function */
180         GC_oom_fn = gc_out_of_memory;
181 }
182
183
184 void gc_call()
185 {
186         if (collectverbose)
187                 dolog("Garbage Collection:  previous/now = %d / %d ",
188                           0, 0);
189
190         GC_gcollect();
191 }
192
193
194 s8 gc_get_heap_size()
195 {
196         return GC_get_heap_size();
197 }
198
199
200 s8 gc_get_free_bytes()
201 {
202         return GC_get_free_bytes();
203 }
204
205
206 s8 gc_get_max_heap_size()
207 {
208         return GC_get_max_heap_size();
209 }
210
211
212 void gc_invoke_finalizers()
213 {
214         GC_invoke_finalizers();
215 }
216
217
218 void gc_finalize_all()
219 {
220         GC_finalize_all();
221 }
222
223
224 /* gc_out_of_memory ************************************************************
225
226    This function is called when boehm detects that it is OOM.
227
228 *******************************************************************************/
229
230 void *gc_out_of_memory()
231 {
232         /* if this happens, we are REALLY out of memory */
233
234         if (in_gc_out_of_memory) {
235                 /* this is all we can do... */
236                 throw_cacao_exception_exit(string_java_lang_InternalError,
237                                                                    "out of memory");
238         }
239
240         in_gc_out_of_memory = true;
241
242         /* try to release some memory */
243
244         gc_call();
245
246         /* now instantiate the exception */
247
248         *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
249
250         in_gc_out_of_memory = false;
251
252         return NULL;
253 }
254
255
256 /*
257  * These are local overrides for various environment variables in Emacs.
258  * Please do not remove this and leave it at the end of the file, where
259  * Emacs will automagically detect them.
260  * ---------------------------------------------------------------------
261  * Local variables:
262  * mode: c
263  * indent-tabs-mode: t
264  * c-basic-offset: 4
265  * tab-width: 4
266  * End:
267  */