[Gc] GC hooks.

Miguel de Icaza miguel@ximian.com
28 May 2003 11:52:17 -0400


--=-mZd+h2w0ubUFWfRrRzXX
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

Hello Hans, Martin,

    We would like to add a few changes to the GC which are required for
our Mono .NET Debugger to work (and also to implement some tricky
functionality like Thread.Abort in the .NET Framework).

    Martin mailed some time ago our current patch, and we would very
much like to get your feedback on whether the patch is correct, or if we
need to do some changes to it, to get it accepted into your
distribution.

    We do not have any pressing need to get it from your distribution,
as we can offer users a modified version of the patch, but we want to
work with you to ensure that our approach is sound.

    I have attached his last set of patches.
    
Miguel

--=-mZd+h2w0ubUFWfRrRzXX
Content-Disposition: attachment; filename=libgc.patch
Content-Transfer-Encoding: quoted-printable
Content-Type: text/x-patch; name=libgc.patch; charset=ISO-8859-1

Index: include/gc.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/public/libgc/include/gc.h,v
retrieving revision 1.1.1.1
diff -u -u -r1.1.1.1 gc.h
--- include/gc.h	31 Mar 2003 14:34:38 -0000	1.1.1.1
+++ include/gc.h	16 May 2003 23:47:09 -0000
@@ -881,6 +881,17 @@
 	GC_PROTO((GC_PTR p));
=20
=20
+typedef struct
+{
+	void (* initialize) (void);
+
+	void (* stop_world) (void);
+	void (* push_all_stacks) (void);
+	void (* start_world) (void);
+} GCThreadFunctions;
+
+extern GCThreadFunctions *gc_thread_vtable;
+
 /* For pthread support, we generally need to intercept a number of 	*/
 /* thread library calls.  We do that here by macro defining them.	*/
=20
Index: linux_threads.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/public/libgc/linux_threads.c,v
retrieving revision 1.1.1.1
diff -u -u -r1.1.1.1 linux_threads.c
--- linux_threads.c	31 Mar 2003 14:33:55 -0000	1.1.1.1
+++ linux_threads.c	16 May 2003 23:49:08 -0000
@@ -945,20 +945,11 @@
 }
=20
 /* Caller holds allocation lock.	*/
-void GC_stop_world()
+static void linux_stop_world()
 {
     register int i;
     register int n_live_threads;
=20
-    /* Make sure all free list construction has stopped before we start. *=
/
-    /* No new construction can start, since free list construction is	*/
-    /* required to acquire and release the GC lock before it starts,	*/
-    /* and we have the lock.						*/
-#   ifdef PARALLEL_MARK
-      GC_acquire_mark_lock();
-      GC_ASSERT(GC_fl_builder_count =3D=3D 0);
-      /* We should have previously waited for it to become zero. */
-#   endif /* PARALLEL_MARK */
     ++GC_stop_count;
     n_live_threads =3D GC_suspend_all();
     if (GC_retry_signals) {
@@ -994,18 +985,35 @@
     	if (0 !=3D sem_wait(&GC_suspend_ack_sem))
 	    ABORT("sem_wait in handler failed");
     }
-#   ifdef PARALLEL_MARK
-      GC_release_mark_lock();
-#   endif
     #if DEBUG_THREADS
       GC_printf1("World stopped from 0x%lx\n", pthread_self());
     #endif
     GC_stopping_thread =3D 0;  /* debugging only */
 }
=20
+/* Caller holds allocation lock.	*/
+void GC_stop_world()
+{
+    /* Make sure all free list construction has stopped before we start. *=
/
+    /* No new construction can start, since free list construction is	*/
+    /* required to acquire and release the GC lock before it starts,	*/
+    /* and we have the lock.						*/
+#   ifdef PARALLEL_MARK
+      GC_acquire_mark_lock();
+      GC_ASSERT(GC_fl_builder_count =3D=3D 0);
+      /* We should have previously waited for it to become zero. */
+#   endif /* PARALLEL_MARK */
+    ++GC_stop_count;
+    gc_thread_vtable->stop_world ();
+#   ifdef PARALLEL_MARK
+      GC_release_mark_lock();
+#   endif
+}
+
+
 /* Caller holds allocation lock, and has held it continuously since	*/
 /* the world stopped.							*/
-void GC_start_world()
+static void linux_start_world()
 {
     pthread_t my_thread =3D pthread_self();
     register int i;
@@ -1045,6 +1053,11 @@
     #endif
 }
=20
+void GC_start_world()
+{
+	gc_thread_vtable->start_world();
+}
+
 # ifdef IA64
 #   define IF_IA64(x) x
 # else
@@ -1052,7 +1065,7 @@
 # endif
 /* We hold allocation lock.  Should do exactly the right thing if the	*/
 /* world is stopped.  Should not fail if it isn't.			*/
-void GC_push_all_stacks()
+static void linux_push_all_stacks()
 {
     int i;
     GC_thread p;
@@ -1111,6 +1124,13 @@
     }
 }
=20
+/* We hold allocation lock.  Should do exactly the right thing if the	*/
+/* world is stopped.  Should not fail if it isn't.			*/
+void GC_push_all_stacks()
+{
+    gc_thread_vtable->push_all_stacks();
+}
+
 #ifdef USE_PROC_FOR_LIBRARIES
 int GC_segment_is_thread_stack(ptr_t lo, ptr_t hi)
 {
@@ -1281,16 +1301,12 @@
 }
 #endif /* GC_DGUX386_THREADS */
=20
-/* We hold the allocation lock.	*/
-void GC_thr_init()
+static void linux_thread_init(void)
 {
     int dummy;
     GC_thread t;
     struct sigaction act;
=20
-    if (GC_thr_initialized) return;
-    GC_thr_initialized =3D TRUE;
-
     if (sem_init(&GC_suspend_ack_sem, 0, 0) !=3D 0)
     	ABORT("sem_init failed");
=20
@@ -1317,11 +1333,6 @@
     if (sigaction(SIG_THR_RESTART, &act, NULL) !=3D 0) {
     	ABORT("Cannot set SIG_THR_RESTART handler");
     }
-#   ifdef HANDLE_FORK
-      /* Prepare for a possible fork.	*/
-        pthread_atfork(GC_fork_prepare_proc, GC_fork_parent_proc,
-	  	       GC_fork_child_proc);
-#   endif /* HANDLE_FORK */
     /* Add the initial thread, so we can stop it.	*/
       t =3D GC_new_thread(pthread_self());
       t -> stack_ptr =3D (ptr_t)(&dummy);
@@ -1339,6 +1350,21 @@
               GC_printf0("Will retry suspend signal if necessary.\n");
 	  }
 #     endif
+}
+
+/* We hold the allocation lock.	*/
+void GC_thr_init()
+{
+    if (GC_thr_initialized) return;
+    GC_thr_initialized =3D TRUE;
+
+    gc_thread_vtable->initialize ();
+
+#   ifdef HANDLE_FORK
+      /* Prepare for a possible fork.	*/
+        pthread_atfork(GC_fork_prepare_proc, GC_fork_parent_proc,
+	  	       GC_fork_child_proc);
+#   endif /* HANDLE_FORK */
=20
     /* Set GC_nprocs.  */
       {
@@ -2000,5 +2026,17 @@
=20
 #endif /* PARALLEL_MARK */
=20
-# endif /* GC_LINUX_THREADS and friends */
+/*
+ * This is used by the Mono Debugger to stop/start the world.
+ */
+GCThreadFunctions linux_thread_vtable =3D {
+	linux_thread_init,
+
+	linux_stop_world,
+	linux_push_all_stacks,
+	linux_start_world
+};
=20
+GCThreadFunctions *gc_thread_vtable =3D &linux_thread_vtable;
+
+# endif /* GC_LINUX_THREADS and friends */

--=-mZd+h2w0ubUFWfRrRzXX--