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