Use message-passing to implement throwTo in the RTS
[ghc-hetmet.git] / rts / sm / MarkWeak.c
index 9d8e8c0..9df39b9 100644 (file)
@@ -22,6 +22,7 @@
 #include "Schedule.h"
 #include "Weak.h"
 #include "Storage.h"
+#include "Threads.h"
 
 /* -----------------------------------------------------------------------------
    Weak Pointers
@@ -80,9 +81,6 @@ StgWeak *old_weak_ptr_list; // also pending finaliser list
 // List of threads found to be unreachable
 StgTSO *resurrected_threads;
 
-// List of blocked threads found to have pending throwTos
-StgTSO *exception_threads;
-
 static void resurrectUnreachableThreads (generation *gen);
 static rtsBool tidyThreadList (generation *gen);
 
@@ -93,7 +91,6 @@ initWeakForGC(void)
     weak_ptr_list = NULL;
     weak_stage = WeakPtrs;
     resurrected_threads = END_TSO_QUEUE;
-    exception_threads = END_TSO_QUEUE;
 }
 
 rtsBool 
@@ -127,14 +124,8 @@ traverseWeakPtrList(void)
              continue;
          }
          
-          info = w->header.info;
-          if (IS_FORWARDING_PTR(info)) {
-             next_w = (StgWeak *)UN_FORWARDING_PTR(info);
-             *last_w = next_w;
-             continue;
-          }
-
-         switch (INFO_PTR_TO_STRUCT(info)->type) {
+          info = get_itbl(w);
+         switch (info->type) {
 
          case WEAK:
              /* Now, check whether the key is reachable.
@@ -292,35 +283,11 @@ static rtsBool tidyThreadList (generation *gen)
         
         next = t->global_link;
         
-        // This is a good place to check for blocked
-        // exceptions.  It might be the case that a thread is
-        // blocked on delivering an exception to a thread that
-        // is also blocked - we try to ensure that this
-        // doesn't happen in throwTo(), but it's too hard (or
-        // impossible) to close all the race holes, so we
-        // accept that some might get through and deal with
-        // them here.  A GC will always happen at some point,
-        // even if the system is otherwise deadlocked.
-        //
-        // If an unreachable thread has blocked
-        // exceptions, we really want to perform the
-        // blocked exceptions rather than throwing
-        // BlockedIndefinitely exceptions.  This is the
-        // only place we can discover such threads.
-        // The target thread might even be
-        // ThreadFinished or ThreadKilled.  Bugs here
-        // will only be seen when running on a
-        // multiprocessor.
-        if (t->blocked_exceptions != END_TSO_QUEUE) {
-            if (tmp == NULL) {
-                evacuate((StgClosure **)&t);
-                flag = rtsTrue;
-            }
-            t->global_link = exception_threads;
-            exception_threads = t;
-            *prev = next;
-            continue;
-        }
+        // if the thread is not masking exceptions but there are
+        // pending exceptions on its queue, then something has gone
+        // wrong:
+        ASSERT(t->blocked_exceptions == END_BLOCKED_EXCEPTIONS_QUEUE
+               || (t->flags & TSO_BLOCKEX));
         
         if (tmp == NULL) {
             // not alive (yet): leave this thread on the
@@ -386,21 +353,17 @@ traverseBlackholeQueue (void)
 }
 
 /* -----------------------------------------------------------------------------
-   After GC, the live weak pointer list may have forwarding pointers
-   on it, because a weak pointer object was evacuated after being
-   moved to the live weak pointer list.  We remove those forwarding
-   pointers here.
-
-   Also, we don't consider weak pointer objects to be reachable, but
-   we must nevertheless consider them to be "live" and retain them.
-   Therefore any weak pointer objects which haven't as yet been
-   evacuated need to be evacuated now.
+   Evacuate every weak pointer object on the weak_ptr_list, and update
+   the link fields.
+
+   ToDo: with a lot of weak pointers, this will be expensive.  We
+   should have a per-GC weak pointer list, just like threads.
    -------------------------------------------------------------------------- */
 
 void
 markWeakPtrList ( void )
 {
-  StgWeak *w, **last_w, *tmp;
+  StgWeak *w, **last_w;
 
   last_w = &weak_ptr_list;
   for (w = weak_ptr_list; w; w = w->link) {
@@ -408,10 +371,13 @@ markWeakPtrList ( void )
       ASSERT(IS_FORWARDING_PTR(w->header.info)
              || w->header.info == &stg_DEAD_WEAK_info 
             || get_itbl(w)->type == WEAK);
-      tmp = w;
-      evacuate((StgClosure **)&tmp);
-      *last_w = w;
-      last_w = &(w->link);
+      evacuate((StgClosure **)last_w);
+      w = *last_w;
+      if (w->header.info == &stg_DEAD_WEAK_info) {
+          last_w = &(((StgDeadWeak*)w)->link);
+      } else {
+          last_w = &(w->link);
+      }
   }
 }