xref: /netbsd-src/external/gpl3/gcc.old/dist/libphobos/libdruntime/gc/proxy.d (revision 627f7eb200a4419d89b531d55fccd2ee3ffdcde0)
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