]> git.llucax.com Git - software/druntime.git/blob - src/gc/basic/gc.d
Don't use dmd directly in the makefiles, use $(DC)
[software/druntime.git] / src / gc / basic / gc.d
1 /**
2  * This module contains the garbage collector front-end.
3  *
4  * Copyright: Copyright (C) 2005-2006 Digital Mars, www.digitalmars.com.
5  *            All rights reserved.
6  * License:
7  *  This software is provided 'as-is', without any express or implied
8  *  warranty. In no event will the authors be held liable for any damages
9  *  arising from the use of this software.
10  *
11  *  Permission is granted to anyone to use this software for any purpose,
12  *  including commercial applications, and to alter it and redistribute it
13  *  freely, in both source and binary form, subject to the following
14  *  restrictions:
15  *
16  *  o  The origin of this software must not be misrepresented; you must not
17  *     claim that you wrote the original software. If you use this software
18  *     in a product, an acknowledgment in the product documentation would be
19  *     appreciated but is not required.
20  *  o  Altered source versions must be plainly marked as such, and must not
21  *     be misrepresented as being the original software.
22  *  o  This notice may not be removed or altered from any source
23  *     distribution.
24  * Authors:   Walter Bright, Sean Kelly
25  */
26
27 module gc.gc;
28
29 private
30 {
31     import gcx;
32     import gcstats;
33     import core.stdc.stdlib;
34
35     version = GCCLASS;
36
37     version( GCCLASS )
38         alias GC gc_t;
39     else
40         alias GC* gc_t;
41
42     gc_t _gc;
43
44     extern (C) void thread_init();
45
46     struct Proxy
47     {
48         extern (C) void function() gc_enable;
49         extern (C) void function() gc_disable;
50         extern (C) void function() gc_collect;
51         extern (C) void function() gc_minimize;
52
53         extern (C) uint function(void*) gc_getAttr;
54         extern (C) uint function(void*, uint) gc_setAttr;
55         extern (C) uint function(void*, uint) gc_clrAttr;
56
57         extern (C) void*  function(size_t, uint) gc_malloc;
58         extern (C) void*  function(size_t, uint) gc_calloc;
59         extern (C) void*  function(void*, size_t, uint ba) gc_realloc;
60         extern (C) size_t function(void*, size_t, size_t) gc_extend;
61         extern (C) size_t function(size_t) gc_reserve;
62         extern (C) void   function(void*) gc_free;
63
64         extern (C) void*   function(void*) gc_addrOf;
65         extern (C) size_t  function(void*) gc_sizeOf;
66
67         extern (C) BlkInfo function(void*) gc_query;
68
69         extern (C) void function(void*) gc_addRoot;
70         extern (C) void function(void*, size_t) gc_addRange;
71
72         extern (C) void function(void*) gc_removeRoot;
73         extern (C) void function(void*) gc_removeRange;
74     }
75
76     Proxy  pthis;
77     Proxy* proxy;
78
79     void initProxy()
80     {
81         pthis.gc_enable = &gc_enable;
82         pthis.gc_disable = &gc_disable;
83         pthis.gc_collect = &gc_collect;
84         pthis.gc_minimize = &gc_minimize;
85
86         pthis.gc_getAttr = &gc_getAttr;
87         pthis.gc_setAttr = &gc_setAttr;
88         pthis.gc_clrAttr = &gc_clrAttr;
89
90         pthis.gc_malloc = &gc_malloc;
91         pthis.gc_calloc = &gc_calloc;
92         pthis.gc_realloc = &gc_realloc;
93         pthis.gc_extend = &gc_extend;
94         pthis.gc_reserve = &gc_reserve;
95         pthis.gc_free = &gc_free;
96
97         pthis.gc_addrOf = &gc_addrOf;
98         pthis.gc_sizeOf = &gc_sizeOf;
99
100         pthis.gc_query = &gc_query;
101
102         pthis.gc_addRoot = &gc_addRoot;
103         pthis.gc_addRange = &gc_addRange;
104
105         pthis.gc_removeRoot = &gc_removeRoot;
106         pthis.gc_removeRange = &gc_removeRange;
107     }
108 }
109
110 extern (C) void gc_init()
111 {
112     version (GCCLASS)
113     {   void* p;
114         ClassInfo ci = GC.classinfo;
115
116         p = malloc(ci.init.length);
117         (cast(byte*)p)[0 .. ci.init.length] = ci.init[];
118         _gc = cast(GC)p;
119     }
120     else
121     {
122         _gc = cast(GC*) calloc(1, GC.sizeof);
123     }
124     _gc.initialize();
125     // NOTE: The GC must initialize the thread library
126     //       before its first collection.
127     thread_init();
128     initProxy();
129 }
130
131 extern (C) void gc_term()
132 {
133     // NOTE: There may be daemons threads still running when this routine is
134     //       called.  If so, cleaning memory out from under then is a good
135     //       way to make them crash horribly.  This probably doesn't matter
136     //       much since the app is supposed to be shutting down anyway, but
137     //       I'm disabling cleanup for now until I can think about it some
138     //       more.
139     //
140     // NOTE: Due to popular demand, this has been re-enabled.  It still has
141     //       the problems mentioned above though, so I guess we'll see.
142     _gc.fullCollectNoStack(); // not really a 'collect all' -- still scans
143                               // static data area, roots, and ranges.
144     _gc.Dtor();
145 }
146
147 extern (C) void gc_enable()
148 {
149     if( proxy is null )
150         return _gc.enable();
151     return proxy.gc_enable();
152 }
153
154 extern (C) void gc_disable()
155 {
156     if( proxy is null )
157         return _gc.disable();
158     return proxy.gc_disable();
159 }
160
161 extern (C) void gc_collect()
162 {
163     if( proxy is null )
164         return _gc.fullCollect();
165     return proxy.gc_collect();
166 }
167
168
169 extern (C) void gc_minimize()
170 {
171     if( proxy is null )
172         return _gc.minimize();
173     return proxy.gc_minimize();
174 }
175
176 extern (C) uint gc_getAttr( void* p )
177 {
178     if( proxy is null )
179         return _gc.getAttr( p );
180     return proxy.gc_getAttr( p );
181 }
182
183 extern (C) uint gc_setAttr( void* p, uint a )
184 {
185     if( proxy is null )
186         return _gc.setAttr( p, a );
187     return proxy.gc_setAttr( p, a );
188 }
189
190 extern (C) uint gc_clrAttr( void* p, uint a )
191 {
192     if( proxy is null )
193         return _gc.clrAttr( p, a );
194     return proxy.gc_clrAttr( p, a );
195 }
196
197 extern (C) void* gc_malloc( size_t sz, uint ba = 0 )
198 {
199     if( proxy is null )
200         return _gc.malloc( sz, ba );
201     return proxy.gc_malloc( sz, ba );
202 }
203
204 extern (C) void* gc_calloc( size_t sz, uint ba = 0 )
205 {
206     if( proxy is null )
207         return _gc.calloc( sz, ba );
208     return proxy.gc_calloc( sz, ba );
209 }
210
211 extern (C) void* gc_realloc( void* p, size_t sz, uint ba = 0 )
212 {
213     if( proxy is null )
214         return _gc.realloc( p, sz, ba );
215     return proxy.gc_realloc( p, sz, ba );
216 }
217
218 extern (C) size_t gc_extend( void* p, size_t mx, size_t sz )
219 {
220     if( proxy is null )
221         return _gc.extend( p, mx, sz );
222     return proxy.gc_extend( p, mx, sz );
223 }
224
225 extern (C) size_t gc_reserve( size_t sz )
226 {
227     if( proxy is null )
228         return _gc.reserve( sz );
229     return proxy.gc_reserve( sz );
230 }
231
232 extern (C) void gc_free( void* p )
233 {
234     if( proxy is null )
235         return _gc.free( p );
236     return proxy.gc_free( p );
237 }
238
239 extern (C) void* gc_addrOf( void* p )
240 {
241     if( proxy is null )
242         return _gc.addrOf( p );
243     return proxy.gc_addrOf( p );
244 }
245
246 extern (C) size_t gc_sizeOf( void* p )
247 {
248     if( proxy is null )
249         return _gc.sizeOf( p );
250     return proxy.gc_sizeOf( p );
251 }
252
253 extern (C) BlkInfo gc_query( void* p )
254 {
255     if( proxy is null )
256         return _gc.query( p );
257     return proxy.gc_query( p );
258 }
259
260 // NOTE: This routine is experimental.  The stats or function name may change
261 //       before it is made officially available.
262 extern (C) GCStats gc_stats()
263 {
264     if( proxy is null )
265     {
266         GCStats stats = void;
267         _gc.getStats( stats );
268         return stats;
269     }
270     // TODO: Add proxy support for this once the layout of GCStats is
271     //       finalized.
272     //return proxy.gc_stats();
273     return GCStats.init;
274 }
275
276 extern (C) void gc_addRoot( void* p )
277 {
278     if( proxy is null )
279         return _gc.addRoot( p );
280     return proxy.gc_addRoot( p );
281 }
282
283 extern (C) void gc_addRange( void* p, size_t sz )
284 {
285     if( proxy is null )
286         return _gc.addRange( p, sz );
287     return proxy.gc_addRange( p, sz );
288 }
289
290 extern (C) void gc_removeRoot( void* p )
291 {
292     if( proxy is null )
293         return _gc.removeRoot( p );
294     return proxy.gc_removeRoot( p );
295 }
296
297 extern (C) void gc_removeRange( void* p )
298 {
299     if( proxy is null )
300         return _gc.removeRange( p );
301     return proxy.gc_removeRange( p );
302 }
303
304 extern (C) Proxy* gc_getProxy()
305 {
306     return &pthis;
307 }
308 import core.stdc.stdio;
309 export extern (C) void gc_setProxy( Proxy* p )
310 {
311     if( proxy !is null )
312     {
313         // TODO: Decide if this is an error condition.
314     }
315     proxy = p;
316     foreach( r; _gc.rootIter )
317         proxy.gc_addRoot( r );
318     foreach( r; _gc.rangeIter )
319         proxy.gc_addRange( r.pbot, r.ptop - r.pbot );
320 }
321
322 export extern (C) void gc_clrProxy()
323 {
324     foreach( r; _gc.rangeIter )
325         proxy.gc_removeRange( r.pbot );
326     foreach( r; _gc.rootIter )
327         proxy.gc_removeRoot( r );
328     proxy = null;
329 }