[boehm] Implement the finalization extension API.
authorRodrigo Kumpera <kumpera@gmail.com>
Fri, 30 May 2014 01:51:29 +0000 (21:51 -0400)
committerRodrigo Kumpera <kumpera@gmail.com>
Fri, 30 May 2014 01:52:29 +0000 (21:52 -0400)
libgc/finalize.c
libgc/include/gc.h
mono/metadata/boehm-gc.c

index 91f6970180cd26352a864464a0ac44184d2a07ce..5626e8721370071bbefdbfb1710911b86a17bb50 100644 (file)
@@ -366,6 +366,15 @@ GC_process_togglerefs (void)
        GC_toggleref_array_size = w;
 }
 
+/* Finalizer proc support */
+static void (*GC_object_finalized_proc) (GC_PTR obj);
+
+void
+GC_set_finalizer_notify_proc (void (*proc) (GC_PTR obj))
+{
+       GC_object_finalized_proc = proc;
+}
+
 
 static void push_and_mark_object (GC_PTR p)
 {
@@ -877,6 +886,10 @@ void GC_finalize()
                 fo_set_next(prev_fo, next_fo);
               }
               GC_fo_entries--;
+
+                         if (GC_object_finalized_proc)
+                                 GC_object_finalized_proc (real_ptr);
+
             /* Add to list of objects awaiting finalization.   */
               fo_set_next(curr_fo, GC_finalize_now);
               GC_finalize_now = curr_fo;
index a3eb3c2dc06e35ff79ed87bf223c85131c8b412a..4693a3d9a5416248700084c6acbb32d2ba3028d4 100644 (file)
@@ -778,6 +778,10 @@ GC_API int GC_unregister_long_link GC_PROTO((GC_PTR * /* link */));
 GC_API void GC_toggleref_register_callback GC_PROTO((int (*proccess_toggleref) (GC_PTR obj)));
 GC_API void GC_toggleref_add (GC_PTR object, int strong_ref);
 
+/* finalizer callback support */
+GC_API void GC_set_finalizer_notify_proc GC_PROTO((void (*object_finalized) (GC_PTR obj)));
+
+
 /* Returns !=0  if GC_invoke_finalizers has something to do.           */
 GC_API int GC_should_invoke_finalizers GC_PROTO((void));
 
index 82bc43bace4ac21cd09bdb1748df53816b41a4c2..a27a004f7c612fdab81257b3d53f250c4166499b 100644 (file)
@@ -59,6 +59,9 @@ boehm_thread_unregister (MonoThreadInfo *p);
 static void
 register_test_toggleref_callback (void);
 
+#define BOEHM_GC_BIT_FINALIZER_AWARE 1
+static MonoGCFinalizerCallbacks fin_callbacks;
+
 static void
 mono_gc_warning (char *msg, GC_word arg)
 {
@@ -1259,6 +1262,10 @@ BOOL APIENTRY mono_gc_dllmain (HMODULE module_handle, DWORD reason, LPVOID reser
 guint
 mono_gc_get_vtable_bits (MonoClass *class)
 {
+       if (fin_callbacks.is_class_finalization_aware) {
+               if (fin_callbacks.is_class_finalization_aware (class))
+                       return BOEHM_GC_BIT_FINALIZER_AWARE;
+       }
        return 0;
 }
 
@@ -1338,4 +1345,29 @@ register_test_toggleref_callback (void)
        mono_gc_toggleref_register_callback (test_toggleref_callback);
 }
 
+static gboolean
+is_finalization_aware (MonoObject *obj)
+{
+       MonoVTable *vt = obj->vtable;
+       return (vt->gc_bits & BOEHM_GC_BIT_FINALIZER_AWARE) == BOEHM_GC_BIT_FINALIZER_AWARE;
+}
+
+static void
+fin_notifier (MonoObject *obj)
+{
+       if (is_finalization_aware (obj))
+               fin_callbacks.object_queued_for_finalization (obj);
+}
+
+void
+mono_gc_register_finalizer_callbacks (MonoGCFinalizerCallbacks *callbacks)
+{
+       if (callbacks->version != MONO_GC_FINALIZER_EXTENSION_VERSION)
+               g_error ("Invalid finalizer callback version. Expected %d but got %d\n", MONO_GC_FINALIZER_EXTENSION_VERSION, callbacks->version);
+
+       fin_callbacks = *callbacks;
+
+       GC_set_finalizer_notify_proc ((void (*) (GC_PTR))fin_notifier);
+}
+
 #endif /* no Boehm GC */