]> git.llucax.com Git - software/druntime.git/blob - src/gc/basic/gc.d
6b2418299c7cbfbaa3ab60b0a865823d37b85d26
[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 import gcx;
30 private import gcstats;
31 private import core.stdc.stdlib;
32
33 version=GCCLASS;
34
35 version (GCCLASS)
36     alias GC gc_t;
37 else
38     alias GC* gc_t;
39
40 gc_t _gc;
41
42 extern (C) void thread_init();
43
44 extern (C) void gc_init()
45 {
46     version (GCCLASS)
47     {   void* p;
48         ClassInfo ci = GC.classinfo;
49
50         p = malloc(ci.init.length);
51         (cast(byte*)p)[0 .. ci.init.length] = ci.init[];
52         _gc = cast(GC)p;
53     }
54     else
55     {
56         _gc = cast(GC*) calloc(1, GC.sizeof);
57     }
58     _gc.initialize();
59     // NOTE: The GC must initialize the thread library
60     //       before its first collection.
61     thread_init();
62 }
63
64 extern (C) void gc_term()
65 {
66     // NOTE: There may be daemons threads still running when this routine is
67     //       called.  If so, cleaning memory out from under then is a good
68     //       way to make them crash horribly.  This probably doesn't matter
69     //       much since the app is supposed to be shutting down anyway, but
70     //       I'm disabling cleanup for now until I can think about it some
71     //       more.
72     //
73     // NOTE: Due to popular demand, this has been re-enabled.  It still has
74     //       the problems mentioned above though, so I guess we'll see.
75     _gc.fullCollectNoStack(); // not really a 'collect all' -- still scans
76                               // static data area, roots, and ranges.
77     _gc.Dtor();
78 }
79
80 extern (C) void gc_enable()
81 {
82     if( proxy is null )
83         return _gc.enable();
84     return proxy.gc_enable();
85 }
86
87 extern (C) void gc_disable()
88 {
89     if( proxy is null )
90         return _gc.disable();
91     return proxy.gc_disable();
92 }
93
94 extern (C) void gc_collect()
95 {
96     if( proxy is null )
97         return _gc.fullCollect();
98     return proxy.gc_collect();
99 }
100
101
102 extern (C) void gc_minimize()
103 {
104     if( proxy is null )
105         return _gc.minimize();
106     return proxy.gc_minimize();
107 }
108
109 extern (C) uint gc_getAttr( void* p )
110 {
111     if( proxy is null )
112         return _gc.getAttr( p );
113     return proxy.gc_getAttr( p );
114 }
115
116 extern (C) uint gc_setAttr( void* p, uint a )
117 {
118     if( proxy is null )
119         return _gc.setAttr( p, a );
120     return proxy.gc_setAttr( p, a );
121 }
122
123 extern (C) uint gc_clrAttr( void* p, uint a )
124 {
125     if( proxy is null )
126         return _gc.clrAttr( p, a );
127     return proxy.gc_clrAttr( p, a );
128 }
129
130 extern (C) void* gc_malloc( size_t sz, uint ba = 0 )
131 {
132     if( proxy is null )
133         return _gc.malloc( sz, ba );
134     return proxy.gc_malloc( sz, ba );
135 }
136
137 extern (C) void* gc_calloc( size_t sz, uint ba = 0 )
138 {
139     if( proxy is null )
140         return _gc.calloc( sz, ba );
141     return proxy.gc_calloc( sz, ba );
142 }
143
144 extern (C) void* gc_realloc( void* p, size_t sz, uint ba = 0 )
145 {
146     if( proxy is null )
147         return _gc.realloc( p, sz, ba );
148     return proxy.gc_realloc( p, sz, ba );
149 }
150
151 extern (C) size_t gc_extend( void* p, size_t mx, size_t sz )
152 {
153     if( proxy is null )
154         return _gc.extend( p, mx, sz );
155     return proxy.gc_extend( p, mx, sz );
156 }
157
158 extern (C) size_t gc_reserve( size_t sz )
159 {
160     if( proxy is null )
161         return _gc.reserve( sz );
162     return proxy.gc_reserve( sz );
163 }
164
165 extern (C) void gc_free( void* p )
166 {
167     if( proxy is null )
168         return _gc.free( p );
169     return proxy.gc_free( p );
170 }
171
172 extern (C) void* gc_addrOf( void* p )
173 {
174     if( proxy is null )
175         return _gc.addrOf( p );
176     return proxy.gc_addrOf( p );
177 }
178
179 extern (C) size_t gc_sizeOf( void* p )
180 {
181     if( proxy is null )
182         return _gc.sizeOf( p );
183     return proxy.gc_sizeOf( p );
184 }
185
186 extern (C) BlkInfo gc_query( void* p )
187 {
188     if( proxy is null )
189         return _gc.query( p );
190     return proxy.gc_query( p );
191 }
192
193 // NOTE: This routine is experimental.  The stats or function name may change
194 //       before it is made officially available.
195 extern (C) GCStats gc_stats()
196 {
197     if( proxy is null )
198     {
199         GCStats stats = void;
200         _gc.getStats( stats );
201         return stats;
202     }
203     // TODO: Add proxy support for this once the layout of GCStats is
204     //       finalized.
205     //return proxy.gc_stats();
206     return GCStats.init;
207 }
208
209 extern (C) void gc_addRoot( void* p )
210 {
211     if( proxy is null )
212         return _gc.addRoot( p );
213     return proxy.gc_addRoot( p );
214 }
215
216 extern (C) void gc_addRange( void* p, size_t sz )
217 {
218     if( proxy is null )
219         return _gc.addRange( p, sz );
220     return proxy.gc_addRange( p, sz );
221 }
222
223 extern (C) void gc_removeRoot( void* p )
224 {
225     if( proxy is null )
226         return _gc.removeRoot( p );
227     return proxy.gc_removeRoot( p );
228 }
229
230 extern (C) void gc_removeRange( void* p )
231 {
232     if( proxy is null )
233         return _gc.removeRange( p );
234     return proxy.gc_removeRange( p );
235 }
236
237 struct Proxy
238 {
239     extern (C) void function() gc_enable;
240     extern (C) void function() gc_disable;
241     extern (C) void function() gc_collect;
242     extern (C) void function() gc_minimize;
243
244     extern (C) uint function(void*) gc_getAttr;
245     extern (C) uint function(void*, uint) gc_setAttr;
246     extern (C) uint function(void*, uint) gc_clrAttr;
247
248     extern (C) void*  function(size_t, uint) gc_malloc;
249     extern (C) void*  function(size_t, uint) gc_calloc;
250     extern (C) void*  function(void*, size_t, uint ba) gc_realloc;
251     extern (C) size_t function(void*, size_t, size_t) gc_extend;
252     extern (C) size_t function(size_t) gc_reserve;
253     extern (C) void   function(void*) gc_free;
254
255     extern (C) void*   function(void*) gc_addrOf;
256     extern (C) size_t  function(void*) gc_sizeOf;
257
258     extern (C) BlkInfo function(void*) gc_query;
259
260     extern (C) void function(void*) gc_addRoot;
261     extern (C) void function(void*, size_t) gc_addRange;
262
263     extern (C) void function(void*) gc_removeRoot;
264     extern (C) void function(void*) gc_removeRange;
265 }
266
267 Proxy  pthis;
268 Proxy* proxy;
269
270 static this()
271 {
272     pthis.gc_enable = &gc_enable;
273     pthis.gc_disable = &gc_disable;
274     pthis.gc_collect = &gc_collect;
275     pthis.gc_minimize = &gc_minimize;
276
277     pthis.gc_getAttr = &gc_getAttr;
278     pthis.gc_setAttr = &gc_setAttr;
279     pthis.gc_clrAttr = &gc_clrAttr;
280
281     pthis.gc_malloc = &gc_malloc;
282     pthis.gc_calloc = &gc_calloc;
283     pthis.gc_realloc = &gc_realloc;
284     pthis.gc_extend = &gc_extend;
285     pthis.gc_reserve = &gc_reserve;
286     pthis.gc_free = &gc_free;
287
288     pthis.gc_addrOf = &gc_addrOf;
289     pthis.gc_sizeOf = &gc_sizeOf;
290
291     pthis.gc_query = &gc_query;
292
293     pthis.gc_addRoot = &gc_addRoot;
294     pthis.gc_addRange = &gc_addRange;
295
296     pthis.gc_removeRoot = &gc_removeRoot;
297     pthis.gc_removeRange = &gc_removeRange;
298 }
299
300 extern (C) Proxy* gc_getProxy()
301 {
302     return &pthis;
303 }
304
305 export extern (C) void gc_setProxy( Proxy* p )
306 {
307     if( proxy !is null )
308     {
309         // TODO: Decide if this is an error condition.
310     }
311     proxy = p;
312     // TODO: Add known ranges and roots to the proxy.
313 }
314
315 export extern (C) void gc_clrProxy()
316 {
317     // TODO: Remove known ranges and roots from the proxy.
318     proxy = null;
319 }