diff --git a/ghc/rts/GC.c b/ghc/rts/GC.c
index 42668e7db5129ec0cae5938f9dec65ca92f92dbf..92a4514ca67fc4930f29346b8904c8fd33c54cd6 100644
--- a/ghc/rts/GC.c
+++ b/ghc/rts/GC.c
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: GC.c,v 1.129 2001/11/28 15:42:05 simonmar Exp $
+ * $Id: GC.c,v 1.130 2002/02/18 13:26:12 sof Exp $
  *
  * (c) The GHC Team 1998-1999
  *
@@ -218,6 +218,8 @@ pop_mark_stack(void)
       
      - free from-space in each step, and set from-space = to-space.
 
+   Locks held: sched_mutex
+
    -------------------------------------------------------------------------- */
 
 void
@@ -958,12 +960,17 @@ GarbageCollect ( void (*get_roots)(evac_fn), rtsBool force_major_gc )
   // Reset the nursery
   resetNurseries();
 
+  // let go of lock (so that it can be re-grabbed below).
+  RELEASE_LOCK(&sched_mutex);
+  
   // start any pending finalizers 
   scheduleFinalizers(old_weak_ptr_list);
   
   // send exceptions to any threads which were about to die 
   resurrectThreads(resurrected_threads);
 
+  ACQUIRE_LOCK(&sched_mutex);
+
   // Update the stable pointer hash table.
   updateStablePtrTable(major_gc);
 
diff --git a/ghc/rts/Schedule.c b/ghc/rts/Schedule.c
index 01c97fce55b1e11a6d68b53d53e7174f0f5b392d..1a3843a50874c43a5445e9339675594bd8b1ab3d 100644
--- a/ghc/rts/Schedule.c
+++ b/ghc/rts/Schedule.c
@@ -1,5 +1,5 @@
 /* ---------------------------------------------------------------------------
- * $Id: Schedule.c,v 1.130 2002/02/16 00:30:05 sof Exp $
+ * $Id: Schedule.c,v 1.131 2002/02/18 13:26:13 sof Exp $
  *
  * (c) The GHC Team, 1998-2000
  *
@@ -595,9 +595,7 @@ schedule( void )
 	/* and SMP mode ..? */
 	releaseCapability(cap);
 #endif
-	RELEASE_LOCK(&sched_mutex);
 	GarbageCollect(GetRoots,rtsTrue);
-	ACQUIRE_LOCK(&sched_mutex);
 	if (   EMPTY_QUEUE(blocked_queue_hd)
 	    && EMPTY_RUN_QUEUE()
 	    && EMPTY_QUEUE(sleeping_queue) ) {
@@ -1344,9 +1342,7 @@ schedule( void )
 #if defined(RTS_SUPPORTS_THREADS)
       IF_DEBUG(scheduler,sched_belch("doing GC"));
 #endif
-      RELEASE_LOCK(&sched_mutex);
       GarbageCollect(GetRoots,rtsFalse);
-      ACQUIRE_LOCK(&sched_mutex);
       ready_to_gc = rtsFalse;
 #ifdef SMP
       broadcastCondition(&gc_pending_cond);
@@ -2320,13 +2316,18 @@ void (*extra_roots)(evac_fn);
 void
 performGC(void)
 {
+  /* Obligated to hold this lock upon entry */
+  ACQUIRE_LOCK(&sched_mutex);
   GarbageCollect(GetRoots,rtsFalse);
+  RELEASE_LOCK(&sched_mutex);
 }
 
 void
 performMajorGC(void)
 {
+  ACQUIRE_LOCK(&sched_mutex);
   GarbageCollect(GetRoots,rtsTrue);
+  RELEASE_LOCK(&sched_mutex);
 }
 
 static void
@@ -2339,8 +2340,10 @@ AllRoots(evac_fn evac)
 void
 performGCWithRoots(void (*get_roots)(evac_fn))
 {
+  ACQUIRE_LOCK(&sched_mutex);
   extra_roots = get_roots;
   GarbageCollect(AllRoots,rtsFalse);
+  RELEASE_LOCK(&sched_mutex);
 }
 
 /* -----------------------------------------------------------------------------
diff --git a/ghc/rts/Weak.c b/ghc/rts/Weak.c
index ef26e3b7ba93c1280cafc5cd7a62effcfa33c924..5c71710a9ebd38d2213614871fe30c4e1d023fd8 100644
--- a/ghc/rts/Weak.c
+++ b/ghc/rts/Weak.c
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: Weak.c,v 1.20 2001/11/26 16:54:22 simonmar Exp $
+ * $Id: Weak.c,v 1.21 2002/02/18 13:26:13 sof Exp $
  *
  * (c) The GHC Team, 1998-1999
  *
@@ -56,6 +56,8 @@ finalizeWeakPointersNow(void)
  * The weak pointer object itself may not be alive - i.e. we may be
  * looking at either an object in from-space or one in to-space.  It
  * doesn't really matter either way.
+ *
+ * Pre-condition: sched_mutex _not_ held.
  */
 
 void