[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