2007-04-02 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / metadata / boehm-gc.c
1 /*
2  * boehm-gc.c: GC implementation using either the installed or included Boehm GC.
3  *
4  */
5
6 #include "config.h"
7 #define GC_I_HIDE_POINTERS
8 #include <mono/os/gc_wrapper.h>
9 #include <mono/metadata/mono-gc.h>
10 #include <mono/metadata/gc-internal.h>
11 #include <mono/metadata/profiler-private.h>
12 #include <mono/utils/mono-logger.h>
13
14 #if HAVE_BOEHM_GC
15
16 static void
17 mono_gc_warning (char *msg, GC_word arg)
18 {
19         mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_GC, msg, (unsigned long)arg);
20 }
21
22 void
23 mono_gc_base_init (void)
24 {
25         GC_no_dls = TRUE;
26         GC_oom_fn = mono_gc_out_of_memory;
27         GC_set_warn_proc (mono_gc_warning);
28         GC_finalize_on_demand = 1;
29         GC_finalizer_notifier = mono_gc_finalize_notify;
30 }
31
32 void
33 mono_gc_collect (int generation)
34 {
35         GC_gcollect ();
36 }
37
38 int
39 mono_gc_max_generation (void)
40 {
41         return 0;
42 }
43
44 int
45 mono_gc_get_generation  (MonoObject *object)
46 {
47         return 0;
48 }
49
50 int
51 mono_gc_collection_count (int generation)
52 {
53         return GC_gc_no;
54 }
55
56 void
57 mono_gc_add_memory_pressure (gint64 value)
58 {
59 }
60
61 gint64
62 mono_gc_get_used_size (void)
63 {
64         return GC_get_heap_size () - GC_get_free_bytes ();
65 }
66
67 gint64
68 mono_gc_get_heap_size (void)
69 {
70         return GC_get_heap_size ();
71 }
72
73 void
74 mono_gc_disable (void)
75 {
76 #ifdef HAVE_GC_ENABLE
77         GC_disable ();
78 #else
79         g_assert_not_reached ();
80 #endif
81 }
82
83 void
84 mono_gc_enable (void)
85 {
86 #ifdef HAVE_GC_ENABLE
87         GC_enable ();
88 #else
89         g_assert_not_reached ();
90 #endif
91 }
92
93 gboolean
94 mono_gc_is_gc_thread (void)
95 {
96 #ifdef USE_INCLUDED_LIBGC
97         return GC_thread_is_registered ();
98 #else
99         return TRUE;
100 #endif
101 }
102
103 extern int GC_thread_register_foreign (void *base_addr);
104
105 gboolean
106 mono_gc_register_thread (void *baseptr)
107 {
108         if (mono_gc_is_gc_thread())
109                 return TRUE;
110 #if defined(USE_INCLUDED_LIBGC) && !defined(PLATFORM_WIN32)
111         return GC_thread_register_foreign (baseptr);
112 #else
113         return FALSE;
114 #endif
115 }
116
117 extern int GC_is_marked (void *p);
118
119 gboolean
120 mono_object_is_alive (MonoObject* o)
121 {
122 #ifdef USE_INCLUDED_LIBGC
123         return GC_is_marked (o);
124 #else
125         return TRUE;
126 #endif
127 }
128
129 #ifdef USE_INCLUDED_LIBGC
130
131 static void
132 on_gc_notification (GCEventType event)
133 {
134         mono_profiler_gc_event ((MonoGCEvent) event, 0);
135 }
136  
137 static void
138 on_gc_heap_resize (size_t new_size)
139 {
140         mono_profiler_gc_heap_resize (new_size);
141 }
142
143 void
144 mono_gc_enable_events (void)
145 {
146         GC_notify_event = on_gc_notification;
147         GC_on_heap_resize = on_gc_heap_resize;
148 }
149
150 #else
151
152 void
153 mono_gc_enable_events (void)
154 {
155 }
156
157 #endif
158
159 void
160 mono_gc_weak_link_add (void **link_addr, MonoObject *obj)
161 {
162         /* libgc requires that we use HIDE_POINTER... */
163         *link_addr = (void*)HIDE_POINTER (obj);
164         GC_GENERAL_REGISTER_DISAPPEARING_LINK (link_addr, obj);
165 }
166
167 void
168 mono_gc_weak_link_remove (void **link_addr)
169 {
170         GC_unregister_disappearing_link (link_addr);
171         *link_addr = NULL;
172 }
173
174 MonoObject*
175 mono_gc_weak_link_get (void **link_addr)
176 {
177         MonoObject *obj = REVEAL_POINTER (*link_addr);
178         if (obj == (MonoObject *) -1)
179                 return NULL;
180         return obj;
181 }
182
183 void*
184 mono_gc_make_descr_from_bitmap (gsize *bitmap, int numbits)
185 {
186         return NULL;
187 }
188
189 void*
190 mono_gc_alloc_fixed (size_t size, void *descr)
191 {
192         return GC_MALLOC (size);
193 }
194
195 void
196 mono_gc_free_fixed (void* addr)
197 {
198 }
199
200 int
201 mono_gc_invoke_finalizers (void)
202 {
203         /* There is a bug in GC_invoke_finalizer () in versions <= 6.2alpha4:
204          * the 'mem_freed' variable is not initialized when there are no
205          * objects to finalize, which leads to strange behavior later on.
206          * The check is necessary to work around that bug.
207          */
208         if (GC_should_invoke_finalizers ())
209                 return GC_invoke_finalizers ();
210         return 0;
211 }
212
213 gboolean
214 mono_gc_pending_finalizers (void)
215 {
216         return GC_should_invoke_finalizers ();
217 }
218
219 void
220 mono_gc_wbarrier_set_field (MonoObject *obj, gpointer field_ptr, MonoObject* value)
221 {
222         *(void**)field_ptr = value;
223 }
224
225 void
226 mono_gc_wbarrier_set_arrayref (MonoArray *arr, gpointer slot_ptr, MonoObject* value)
227 {
228         *(void**)slot_ptr = value;
229 }
230
231 void
232 mono_gc_wbarrier_arrayref_copy (MonoArray *arr, gpointer slot_ptr, int count)
233 {
234         /* no need to do anything */
235 }
236
237 void
238 mono_gc_wbarrier_generic_store (gpointer ptr, MonoObject* value)
239 {
240         *(void**)ptr = value;
241 }
242
243 void
244 mono_gc_wbarrier_value_copy (gpointer dest, gpointer src, int count, MonoClass *klass)
245 {
246 }
247
248 void
249 mono_gc_wbarrier_object (MonoObject *object)
250 {
251 }
252
253 #endif /* no Boehm GC */
254