[MLton] cvs commit: thread tweaks

Stephen Weeks sweeks@mlton.org
Fri, 30 Apr 2004 17:33:46 -0700


sweeks      04/04/30 17:33:45

  Modified:    runtime/Posix/Signal resetPending.c
               runtime  gc.c
               basis-library/mlton thread.sml
  Log:
  MAIL thread tweaks
  
  In gc.c, abstracted out functions atomic{Begin,End} and
  maybeSwitchToHandler.  Eliminated the distinction between startHandler
  and GC_startHandler, and changed the call to GC_startHandler from
  thread.sml so that it is within a critical section, which is what
  GC_startHandler now expects.
  
  Fixed a type warning in the prototype for Posix_Signal_resetPending.

Revision  Changes    Path
1.2       +1 -1      mlton/runtime/Posix/Signal/resetPending.c

Index: resetPending.c
===================================================================
RCS file: /cvsroot/mlton/mlton/runtime/Posix/Signal/resetPending.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- resetPending.c	29 Apr 2004 02:58:59 -0000	1.1
+++ resetPending.c	1 May 2004 00:33:44 -0000	1.2
@@ -8,7 +8,7 @@
 
 extern struct GC_state gcState;
 
-bool Posix_Signal_resetPending () {
+void Posix_Signal_resetPending () {
 	if (DEBUG_SIGNALS)
 		fprintf (stderr, "Posix_Signal_resetPending ()\n");
 	sigemptyset (&gcState.signalsPending);



1.181     +36 -49    mlton/runtime/gc.c

Index: gc.c
===================================================================
RCS file: /cvsroot/mlton/mlton/runtime/gc.c,v
retrieving revision 1.180
retrieving revision 1.181
diff -u -r1.180 -r1.181
--- gc.c	30 Apr 2004 01:04:33 -0000	1.180
+++ gc.c	1 May 2004 00:33:44 -0000	1.181
@@ -1294,13 +1294,23 @@
 /*                         enter and leave                          */
 /* ---------------------------------------------------------------- */
 
+static inline void atomicBegin (GC_state s) {
+	s->canHandle++;
+	if (0 == s->limit)
+		s->limit = s->limitPlusSlop - LIMIT_SLOP;
+}
+
+static inline void atomicEnd (GC_state s) {
+	s->canHandle--;
+	if (0 == s->canHandle and s->signalIsPending)
+		s->limit = 0;
+}
+
 /* enter and leave should be called at the start and end of every GC function
  * that is exported to the outside world.  They make sure that the function
  * is run in a critical section and check the GC invariant.
- * They are a bit tricky because of the case when the runtime system is invoked
- * from within an ML signal handler.
  */
-void enter (GC_state s) {
+static void enter (GC_state s) {
 	if (DEBUG)
 		fprintf (stderr, "enter\n");
 	/* used needs to be set because the mutator has changed s->stackTop. */
@@ -1308,26 +1318,20 @@
 	s->currentThread->exnStack = s->exnStack;
 	if (DEBUG) 
 		GC_display (s, stderr);
-	s->canHandle++;
-	unless (s->inSignalHandler) {
-		if (0 == s->limit)
-			s->limit = s->limitPlusSlop - LIMIT_SLOP;
-	}
+	atomicBegin (s);
 	assert (invariant (s));
 	if (DEBUG)
 		fprintf (stderr, "enter ok\n");
 }
 
-void leave (GC_state s) {
+static void leave (GC_state s) {
 	if (DEBUG)
 		fprintf (stderr, "leave\n");
 	/* The mutator frontier invariant may not hold
 	 * for functions that don't ensureBytesFree.
 	 */
 	assert (mutatorInvariant (s, FALSE, TRUE));
-	s->canHandle--;
-	if (s->canHandle == 0 and s->signalIsPending)
-		s->limit = 0;
+	atomicEnd (s);
 	if (DEBUG)
 		fprintf (stderr, "leave ok\n");
 }
@@ -3075,7 +3079,12 @@
 	setStack (s);
 }
 
-static void startHandler (GC_state s) {
+/* GC_startHandler does not do an enter()/leave(), even though it is exported.
+ * The basis library uses it via _ffi, not _prim, and so does not treat it as a
+ * runtime call -- so the invariant in enter would fail miserably.  It is OK
+ * because GC_startHandler must be called from within a critical section.
+ */
+inline void GC_startHandler (GC_state s) {
 	/* Switch to the signal handler thread. */
 	if (DEBUG_SIGNALS) {
 		fprintf (stderr, "switching to signal handler\n");
@@ -3095,6 +3104,13 @@
 	s->canHandle = 2;
 }
 
+static inline void maybeSwitchToHandler (GC_state s) {
+	if (s->canHandle == 1 and s->signalIsPending) {
+		GC_startHandler (s);
+		switchToThread (s, s->signalHandler);
+	}
+}
+
 void GC_switchToThread (GC_state s, GC_thread t, uint ensureBytesFree) {
 	if (DEBUG_THREADS)
 		fprintf (stderr, "GC_switchToThread (0x%08x, %u)\n", (uint)t, ensureBytesFree);
@@ -3108,10 +3124,7 @@
 		s->currentThread->bytesNeeded = ensureBytesFree;
 		switchToThread (s, t);
 		s->canHandle--;
-		if (s->canHandle == 1 and s->signalIsPending) {
-			startHandler (s);
-			switchToThread (s, s->signalHandler);
-		}
+		maybeSwitchToHandler (s);
 		ensureMutatorInvariant (s, FALSE);
 		assert (mutatorFrontierInvariant(s));
 		assert (mutatorStackInvariant(s));
@@ -3120,19 +3133,12 @@
 		/* BEGIN: enter(s); */
 		s->currentThread->stack->used = currentStackUsed (s);
 		s->currentThread->exnStack = s->exnStack;
-		s->canHandle++;
-		unless (s->inSignalHandler) {
-			if (0 == s->limit)
-				s->limit = s->limitPlusSlop - LIMIT_SLOP;
-		}
+		atomicBegin (s);
 		/* END: enter(s); */
 		s->currentThread->bytesNeeded = ensureBytesFree;
 		switchToThread (s, t);
 		s->canHandle--;
-		if (s->canHandle == 1 and s->signalIsPending) {
-			startHandler (s);
-			switchToThread (s, s->signalHandler);
-		}
+		maybeSwitchToHandler (s);
 		/* BEGIN: ensureMutatorInvariant */
 		if (not (mutatorFrontierInvariant(s))
 			or not (mutatorStackInvariant(s))) {
@@ -3142,31 +3148,15 @@
 		} 
 		/* END: ensureMutatorInvariant */
 		else {
-		/* BEGIN: leave(s); */
-		s->canHandle--;
-		if (s->canHandle == 0 and s->signalIsPending)
-			s->limit = 0;
-		/* END: leave(s); */
+			/* BEGIN: leave(s); */
+			atomicEnd (s);
+			/* END: leave(s); */
 		}
 	}
 	assert (mutatorFrontierInvariant(s));
 	assert (mutatorStackInvariant(s));
 }
 
-/* GC_startHandler does not do an enter()/leave(), even though it is exported.
- * The basis library uses it via _ffi, not _prim, and so does not treat it as a
- * runtime call -- so the invariant in enter would fail miserably. It simulates
- * the relevant part of enter() by incrementing s->canHandle and resetting the 
- * limit; it simulates the leave by decrementing s->canHandle.
- */
-void GC_startHandler (GC_state s) {
-	s->canHandle++;
-	if (0 == s->limit)
-		s->limit = s->limitPlusSlop - LIMIT_SLOP;
-	startHandler (s);
-	s->canHandle--;
-}
-
 void GC_gc (GC_state s, uint bytesRequested, bool force,
 		string file, int line) {
 	if (DEBUG or s->messages)
@@ -3178,10 +3168,7 @@
 	if (0 == bytesRequested)
 		bytesRequested = LIMIT_SLOP;
 	s->currentThread->bytesNeeded = bytesRequested;
-	if (s->canHandle == 1 and s->signalIsPending) {
-		startHandler(s);
-		switchToThread (s, s->signalHandler);
-	}
+ 	maybeSwitchToHandler (s);
 	ensureMutatorInvariant (s, force);
 	assert (mutatorFrontierInvariant(s));
 	assert (mutatorStackInvariant(s));



1.26      +2 -2      mlton/basis-library/mlton/thread.sml

Index: thread.sml
===================================================================
RCS file: /cvsroot/mlton/mlton/basis-library/mlton/thread.sml,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -r1.25 -r1.26
--- thread.sml	29 Apr 2004 02:58:58 -0000	1.25
+++ thread.sml	1 May 2004 00:33:45 -0000	1.26
@@ -260,9 +260,9 @@
    fun switchToHandler () =
       let
 	 (* Atomic 0 *)
-	 val () = Prim.startHandler () (* implicit atomicBegin() *)
-         (* Atomic 1 *)
 	 val () = atomicBegin ()
+         (* Atomic 1 *)
+	 val () = Prim.startHandler ()
          (* Atomic 2 *)
       in
 	 case !signalHandler of