2 * Contains the external GC interface.
4 * Copyright: D Language Foundation 2005 - 2021.
5 * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
6 * Authors: Walter Bright, Sean Kelly
8 module core
.internal
.gc
.proxy
;
10 import core
.internal
.gc
.impl
.proto
.gc
;
11 import core
.gc
.config
;
12 import core
.gc
.gcinterface
;
13 import core
.gc
.registry
: createGCInstance
;
15 static import core
.memory
;
19 static import core
.memory
;
20 alias BlkInfo
= core
.memory
.GC
.BlkInfo
;
22 import core
.internal
.spinlock
;
23 static SpinLock instanceLock
;
25 __gshared
bool isInstanceInit
= false;
26 __gshared GC _instance
= new ProtoGC();
27 __gshared GC proxiedGC
; // used to iterate roots of Windows DLLs
29 pragma (inline
, true) @trusted @nogc nothrow
30 GC
instance() { return _instance
; }
35 import core
.attribute
: weak
;
37 // do not import GC modules, they might add a dependency to this whole module
38 void _d_register_conservative_gc();
39 void _d_register_manual_gc();
41 // if you don't want to include the default GCs, replace during link by another implementation
42 void* register_default_gcs() @weak
44 pragma(inline
, false);
45 // do not call, they register implicitly through pragma(crt_constructor)
46 // avoid being optimized away
47 auto reg1
= &_d_register_conservative_gc
;
48 auto reg2
= &_d_register_manual_gc
;
49 return reg1
< reg2 ? reg1
: reg2
;
57 register_default_gcs();
59 auto protoInstance
= instance
;
60 auto newInstance
= createGCInstance(config
.gc
);
61 if (newInstance
is null)
63 import core
.stdc
.stdio
: fprintf
, stderr
;
64 import core
.stdc
.stdlib
: exit
;
65 import core
.atomic
: atomicLoad
;
67 fprintf(atomicLoad(stderr
), "No GC was initialized, please recheck the name of the selected GC ('%.*s').\n", cast(int)config
.gc
.length
, config
.gc
.ptr
);
68 instanceLock
.unlock();
71 // Shouldn't get here.
74 _instance
= newInstance
;
75 // Transfer all ranges and roots to the real GC.
76 (cast(ProtoGC
) protoInstance
).transferRangesAndRoots();
77 isInstanceInit
= true;
79 instanceLock
.unlock();
82 void gc_init_nothrow() nothrow
86 import core
.internal
.abort
;
87 abort("Cannot initialize the garbage collector.\n");
97 switch (config
.cleanup
)
100 import core
.stdc
.stdio
: fprintf
, stderr
;
101 import core
.atomic
: atomicLoad
;
103 fprintf(atomicLoad(stderr
), "Unknown GC cleanup method, please recheck ('%.*s').\n",
104 cast(int)config
.cleanup
.length
, config
.cleanup
.ptr
);
112 instance
.runFinalizers((cast(ubyte*)null)[0 .. size_t
.max
]);
129 void gc_collect() nothrow
134 void gc_minimize() nothrow
139 uint gc_getAttr( void* p
) nothrow
141 return instance
.getAttr(p
);
144 uint gc_setAttr( void* p
, uint a
) nothrow
146 return instance
.setAttr(p
, a
);
149 uint gc_clrAttr( void* p
, uint a
) nothrow
151 return instance
.clrAttr(p
, a
);
154 void* gc_malloc( size_t sz
, uint ba
= 0, const scope TypeInfo ti
= null ) nothrow
156 return instance
.malloc(sz
, ba
, ti
);
159 BlkInfo
gc_qalloc( size_t sz
, uint ba
= 0, const scope TypeInfo ti
= null ) nothrow
161 return instance
.qalloc( sz
, ba
, ti
);
164 void* gc_calloc( size_t sz
, uint ba
= 0, const scope TypeInfo ti
= null ) nothrow
166 return instance
.calloc( sz
, ba
, ti
);
169 void* gc_realloc( void* p
, size_t sz
, uint ba
= 0, const scope TypeInfo ti
= null ) nothrow
171 return instance
.realloc( p
, sz
, ba
, ti
);
174 size_t
gc_extend( void* p
, size_t mx
, size_t sz
, const scope TypeInfo ti
= null ) nothrow
176 return instance
.extend( p
, mx
, sz
,ti
);
179 size_t
gc_reserve( size_t sz
) nothrow
181 return instance
.reserve( sz
);
184 void gc_free( void* p
) nothrow @nogc
186 return instance
.free( p
);
189 void* gc_addrOf( void* p
) nothrow @nogc
191 return instance
.addrOf( p
);
194 size_t
gc_sizeOf( void* p
) nothrow @nogc
196 return instance
.sizeOf( p
);
199 BlkInfo
gc_query( void* p
) nothrow
201 return instance
.query( p
);
204 core
.memory
.GC
.Stats
gc_stats() @safe nothrow @nogc
206 return instance
.stats();
209 core
.memory
.GC
.ProfileStats
gc_profileStats() @safe nothrow @nogc
211 return instance
.profileStats();
214 void gc_addRoot( void* p
) nothrow @nogc
216 return instance
.addRoot( p
);
219 void gc_addRange( void* p
, size_t sz
, const TypeInfo ti
= null ) nothrow @nogc
221 return instance
.addRange( p
, sz
, ti
);
224 void gc_removeRoot( void* p
) nothrow
226 return instance
.removeRoot( p
);
229 void gc_removeRange( void* p
) nothrow
231 return instance
.removeRange( p
);
234 void gc_runFinalizers(const scope void[] segment
) nothrow
236 return instance
.runFinalizers( segment
);
239 bool gc_inFinalizer() nothrow @nogc @safe
241 return instance
.inFinalizer();
244 ulong gc_allocatedInCurrentThread() nothrow
246 return instance
.allocatedInCurrentThread();
249 void[] gc_getArrayUsed(void *ptr
, bool atomic
) nothrow
251 return instance
.getArrayUsed( ptr
, atomic
);
254 bool gc_expandArrayUsed(void[] slice
, size_t newUsed
, bool atomic
) nothrow
256 return instance
.expandArrayUsed( slice
, newUsed
, atomic
);
259 size_t
gc_reserveArrayCapacity(void[] slice
, size_t request
, bool atomic
) nothrow
261 return instance
.reserveArrayCapacity( slice
, request
, atomic
);
264 bool gc_shrinkArrayUsed(void[] slice
, size_t existingUsed
, bool atomic
) nothrow
266 return instance
.shrinkArrayUsed( slice
, existingUsed
, atomic
);
269 GC
gc_getProxy() nothrow
276 void gc_setProxy( GC proxy
)
278 foreach (root
; instance
.rootIter
)
283 foreach (range
; instance
.rangeIter
)
285 proxy
.addRange(range
.pbot
, range
.ptop
- range
.pbot
, range
.ti
);
288 proxiedGC
= instance
; // remember initial GC to later remove roots
294 foreach (root
; proxiedGC
.rootIter
)
296 instance
.removeRoot(root
);
299 foreach (range
; proxiedGC
.rangeIter
)
301 instance
.removeRange(range
);
304 _instance
= proxiedGC
;