1 /** 2 * Contains the external GC interface. 3 * 4 * Copyright: Copyright Digital Mars 2005 - 2016. 5 * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 * Authors: Walter Bright, Sean Kelly 7 */ 8 9 /* Copyright Digital Mars 2005 - 2016. 10 * Distributed under the Boost Software License, Version 1.0. 11 * (See accompanying file LICENSE or copy at 12 * http://www.boost.org/LICENSE_1_0.txt) 13 */ 14 module gc.proxy; 15 16 import gc.impl.conservative.gc; 17 import gc.impl.manual.gc; 18 import gc.config; 19 import gc.gcinterface; 20 21 static import core.memory; 22 23 private 24 { 25 static import core.memory; 26 alias BlkInfo = core.memory.GC.BlkInfo; 27 28 extern (C) void thread_init(); 29 extern (C) void thread_term(); 30 31 __gshared GC instance; 32 __gshared GC proxiedGC; // used to iterate roots of Windows DLLs 33 34 } 35 36 37 extern (C) 38 { 39 gc_init()40 void gc_init() 41 { 42 config.initialize(); 43 ManualGC.initialize(instance); 44 ConservativeGC.initialize(instance); 45 if (instance is null) 46 { 47 import core.stdc.stdio : fprintf, stderr; 48 import core.stdc.stdlib : exit; 49 50 fprintf(stderr, "No GC was initialized, please recheck the name of the selected GC ('%.*s').\n", cast(int)config.gc.length, config.gc.ptr); 51 exit(1); 52 } 53 54 // NOTE: The GC must initialize the thread library 55 // before its first collection. 56 thread_init(); 57 } 58 gc_term()59 void gc_term() 60 { 61 // NOTE: There may be daemons threads still running when this routine is 62 // called. If so, cleaning memory out from under then is a good 63 // way to make them crash horribly. This probably doesn't matter 64 // much since the app is supposed to be shutting down anyway, but 65 // I'm disabling cleanup for now until I can think about it some 66 // more. 67 // 68 // NOTE: Due to popular demand, this has been re-enabled. It still has 69 // the problems mentioned above though, so I guess we'll see. 70 71 instance.collectNoStack(); // not really a 'collect all' -- still scans 72 // static data area, roots, and ranges. 73 74 thread_term(); 75 76 ManualGC.finalize(instance); 77 ConservativeGC.finalize(instance); 78 } 79 gc_enable()80 void gc_enable() 81 { 82 instance.enable(); 83 } 84 gc_disable()85 void gc_disable() 86 { 87 instance.disable(); 88 } 89 gc_collect()90 void gc_collect() nothrow 91 { 92 instance.collect(); 93 } 94 gc_minimize()95 void gc_minimize() nothrow 96 { 97 instance.minimize(); 98 } 99 gc_getAttr(void * p)100 uint gc_getAttr( void* p ) nothrow 101 { 102 return instance.getAttr(p); 103 } 104 gc_setAttr(void * p,uint a)105 uint gc_setAttr( void* p, uint a ) nothrow 106 { 107 return instance.setAttr(p, a); 108 } 109 gc_clrAttr(void * p,uint a)110 uint gc_clrAttr( void* p, uint a ) nothrow 111 { 112 return instance.clrAttr(p, a); 113 } 114 115 void* gc_malloc( size_t sz, uint ba = 0, const TypeInfo ti = null ) nothrow 116 { 117 return instance.malloc(sz, ba, ti); 118 } 119 120 BlkInfo gc_qalloc( size_t sz, uint ba = 0, const TypeInfo ti = null ) nothrow 121 { 122 return instance.qalloc( sz, ba, ti ); 123 } 124 125 void* gc_calloc( size_t sz, uint ba = 0, const TypeInfo ti = null ) nothrow 126 { 127 return instance.calloc( sz, ba, ti ); 128 } 129 130 void* gc_realloc( void* p, size_t sz, uint ba = 0, const TypeInfo ti = null ) nothrow 131 { 132 return instance.realloc( p, sz, ba, ti ); 133 } 134 135 size_t gc_extend( void* p, size_t mx, size_t sz, const TypeInfo ti = null ) nothrow 136 { 137 return instance.extend( p, mx, sz,ti ); 138 } 139 gc_reserve(size_t sz)140 size_t gc_reserve( size_t sz ) nothrow 141 { 142 return instance.reserve( sz ); 143 } 144 gc_free(void * p)145 void gc_free( void* p ) nothrow 146 { 147 return instance.free( p ); 148 } 149 gc_addrOf(void * p)150 void* gc_addrOf( void* p ) nothrow 151 { 152 return instance.addrOf( p ); 153 } 154 gc_sizeOf(void * p)155 size_t gc_sizeOf( void* p ) nothrow 156 { 157 return instance.sizeOf( p ); 158 } 159 gc_query(void * p)160 BlkInfo gc_query( void* p ) nothrow 161 { 162 return instance.query( p ); 163 } 164 gc_stats()165 core.memory.GC.Stats gc_stats() nothrow 166 { 167 return instance.stats(); 168 } 169 gc_addRoot(void * p)170 void gc_addRoot( void* p ) nothrow 171 { 172 return instance.addRoot( p ); 173 } 174 175 void gc_addRange( void* p, size_t sz, const TypeInfo ti = null ) nothrow 176 { 177 return instance.addRange( p, sz, ti ); 178 } 179 gc_removeRoot(void * p)180 void gc_removeRoot( void* p ) nothrow 181 { 182 return instance.removeRoot( p ); 183 } 184 gc_removeRange(void * p)185 void gc_removeRange( void* p ) nothrow 186 { 187 return instance.removeRange( p ); 188 } 189 gc_runFinalizers(in void[]segment)190 void gc_runFinalizers( in void[] segment ) nothrow 191 { 192 return instance.runFinalizers( segment ); 193 } 194 gc_inFinalizer()195 bool gc_inFinalizer() nothrow 196 { 197 return instance.inFinalizer(); 198 } 199 gc_getProxy()200 GC gc_getProxy() nothrow 201 { 202 return instance; 203 } 204 205 export 206 { gc_setProxy(GC proxy)207 void gc_setProxy( GC proxy ) 208 { 209 foreach (root; instance.rootIter) 210 { 211 proxy.addRoot(root); 212 } 213 214 foreach (range; instance.rangeIter) 215 { 216 proxy.addRange(range.pbot, range.ptop - range.pbot, range.ti); 217 } 218 219 proxiedGC = instance; // remember initial GC to later remove roots 220 instance = proxy; 221 } 222 gc_clrProxy()223 void gc_clrProxy() 224 { 225 foreach (root; proxiedGC.rootIter) 226 { 227 instance.removeRoot(root); 228 } 229 230 foreach (range; proxiedGC.rangeIter) 231 { 232 instance.removeRange(range); 233 } 234 235 instance = proxiedGC; 236 proxiedGC = null; 237 } 238 } 239 } 240