proxy.d revision 1.1.1.1
1/** 2 * Contains the external GC interface. 3 * 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 7 */ 8module core.internal.gc.proxy; 9 10import core.internal.gc.impl.proto.gc; 11import core.gc.config; 12import core.gc.gcinterface; 13import core.gc.registry : createGCInstance; 14 15static import core.memory; 16 17private 18{ 19 static import core.memory; 20 alias BlkInfo = core.memory.GC.BlkInfo; 21 22 import core.internal.spinlock; 23 static SpinLock instanceLock; 24 25 __gshared bool isInstanceInit = false; 26 __gshared GC _instance = new ProtoGC(); 27 __gshared GC proxiedGC; // used to iterate roots of Windows DLLs 28 29 pragma (inline, true) @trusted @nogc nothrow 30 GC instance() { return _instance; } 31} 32 33extern (C) 34{ 35 import core.attribute : weak; 36 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(); 40 41 // if you don't want to include the default GCs, replace during link by another implementation 42 void* register_default_gcs() @weak 43 { 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; 50 } 51 52 void gc_init() 53 { 54 instanceLock.lock(); 55 if (!isInstanceInit) 56 { 57 register_default_gcs(); 58 config.initialize(); 59 auto protoInstance = instance; 60 auto newInstance = createGCInstance(config.gc); 61 if (newInstance is null) 62 { 63 import core.stdc.stdio : fprintf, stderr; 64 import core.stdc.stdlib : exit; 65 66 fprintf(stderr, "No GC was initialized, please recheck the name of the selected GC ('%.*s').\n", cast(int)config.gc.length, config.gc.ptr); 67 instanceLock.unlock(); 68 exit(1); 69 70 // Shouldn't get here. 71 assert(0); 72 } 73 _instance = newInstance; 74 // Transfer all ranges and roots to the real GC. 75 (cast(ProtoGC) protoInstance).transferRangesAndRoots(); 76 isInstanceInit = true; 77 } 78 instanceLock.unlock(); 79 } 80 81 void gc_init_nothrow() nothrow 82 { 83 scope(failure) 84 { 85 import core.internal.abort; 86 abort("Cannot initialize the garbage collector.\n"); 87 assert(0); 88 } 89 gc_init(); 90 } 91 92 void gc_term() 93 { 94 if (isInstanceInit) 95 { 96 switch (config.cleanup) 97 { 98 default: 99 import core.stdc.stdio : fprintf, stderr; 100 fprintf(stderr, "Unknown GC cleanup method, please recheck ('%.*s').\n", 101 cast(int)config.cleanup.length, config.cleanup.ptr); 102 break; 103 case "none": 104 break; 105 case "collect": 106 // NOTE: There may be daemons threads still running when this routine is 107 // called. If so, cleaning memory out from under then is a good 108 // way to make them crash horribly. This probably doesn't matter 109 // much since the app is supposed to be shutting down anyway, but 110 // I'm disabling cleanup for now until I can think about it some 111 // more. 112 // 113 // NOTE: Due to popular demand, this has been re-enabled. It still has 114 // the problems mentioned above though, so I guess we'll see. 115 116 instance.collectNoStack(); // not really a 'collect all' -- still scans 117 // static data area, roots, and ranges. 118 break; 119 case "finalize": 120 instance.runFinalizers((cast(ubyte*)null)[0 .. size_t.max]); 121 break; 122 } 123 destroy(instance); 124 } 125 } 126 127 void gc_enable() 128 { 129 instance.enable(); 130 } 131 132 void gc_disable() 133 { 134 instance.disable(); 135 } 136 137 void gc_collect() nothrow 138 { 139 instance.collect(); 140 } 141 142 void gc_minimize() nothrow 143 { 144 instance.minimize(); 145 } 146 147 uint gc_getAttr( void* p ) nothrow 148 { 149 return instance.getAttr(p); 150 } 151 152 uint gc_setAttr( void* p, uint a ) nothrow 153 { 154 return instance.setAttr(p, a); 155 } 156 157 uint gc_clrAttr( void* p, uint a ) nothrow 158 { 159 return instance.clrAttr(p, a); 160 } 161 162 void* gc_malloc( size_t sz, uint ba = 0, const scope TypeInfo ti = null ) nothrow 163 { 164 return instance.malloc(sz, ba, ti); 165 } 166 167 BlkInfo gc_qalloc( size_t sz, uint ba = 0, const scope TypeInfo ti = null ) nothrow 168 { 169 return instance.qalloc( sz, ba, ti ); 170 } 171 172 void* gc_calloc( size_t sz, uint ba = 0, const scope TypeInfo ti = null ) nothrow 173 { 174 return instance.calloc( sz, ba, ti ); 175 } 176 177 void* gc_realloc( void* p, size_t sz, uint ba = 0, const scope TypeInfo ti = null ) nothrow 178 { 179 return instance.realloc( p, sz, ba, ti ); 180 } 181 182 size_t gc_extend( void* p, size_t mx, size_t sz, const scope TypeInfo ti = null ) nothrow 183 { 184 return instance.extend( p, mx, sz,ti ); 185 } 186 187 size_t gc_reserve( size_t sz ) nothrow 188 { 189 return instance.reserve( sz ); 190 } 191 192 void gc_free( void* p ) nothrow @nogc 193 { 194 return instance.free( p ); 195 } 196 197 void* gc_addrOf( void* p ) nothrow @nogc 198 { 199 return instance.addrOf( p ); 200 } 201 202 size_t gc_sizeOf( void* p ) nothrow @nogc 203 { 204 return instance.sizeOf( p ); 205 } 206 207 BlkInfo gc_query( void* p ) nothrow 208 { 209 return instance.query( p ); 210 } 211 212 core.memory.GC.Stats gc_stats() @safe nothrow @nogc 213 { 214 return instance.stats(); 215 } 216 217 core.memory.GC.ProfileStats gc_profileStats() @safe nothrow @nogc 218 { 219 return instance.profileStats(); 220 } 221 222 void gc_addRoot( void* p ) nothrow @nogc 223 { 224 return instance.addRoot( p ); 225 } 226 227 void gc_addRange( void* p, size_t sz, const TypeInfo ti = null ) nothrow @nogc 228 { 229 return instance.addRange( p, sz, ti ); 230 } 231 232 void gc_removeRoot( void* p ) nothrow 233 { 234 return instance.removeRoot( p ); 235 } 236 237 void gc_removeRange( void* p ) nothrow 238 { 239 return instance.removeRange( p ); 240 } 241 242 void gc_runFinalizers(const scope void[] segment ) nothrow 243 { 244 return instance.runFinalizers( segment ); 245 } 246 247 bool gc_inFinalizer() nothrow @nogc @safe 248 { 249 return instance.inFinalizer(); 250 } 251 252 ulong gc_allocatedInCurrentThread() nothrow 253 { 254 return instance.allocatedInCurrentThread(); 255 } 256 257 GC gc_getProxy() nothrow 258 { 259 return instance; 260 } 261 262 export 263 { 264 void gc_setProxy( GC proxy ) 265 { 266 foreach (root; instance.rootIter) 267 { 268 proxy.addRoot(root); 269 } 270 271 foreach (range; instance.rangeIter) 272 { 273 proxy.addRange(range.pbot, range.ptop - range.pbot, range.ti); 274 } 275 276 proxiedGC = instance; // remember initial GC to later remove roots 277 _instance = proxy; 278 } 279 280 void gc_clrProxy() 281 { 282 foreach (root; proxiedGC.rootIter) 283 { 284 instance.removeRoot(root); 285 } 286 287 foreach (range; proxiedGC.rangeIter) 288 { 289 instance.removeRange(range); 290 } 291 292 _instance = proxiedGC; 293 proxiedGC = null; 294 } 295 } 296} 297