RTS tidyup sweep, first phase
[ghc-hetmet.git] / rts / STM.c
index c43e7ca..723f77a 100644 (file)
--- a/rts/STM.c
+++ b/rts/STM.c
  * (d) release the locks on the TVars, writing updates to them in the case of a 
  * commit, (e) unlock the STM.
  *
- * Queues of waiting threads hang off the first_watch_queue_entry field of each
- * TVar.  This may only be manipulated when holding that TVar's lock.  In
- * particular, when a thread is putting itself to sleep, it mustn't release
- * the TVar's lock until it has added itself to the wait queue and marked its
- * TSO as BlockedOnSTM -- this makes sure that other threads will know to wake it.
+ * Queues of waiting threads hang off the first_watch_queue_entry
+ * field of each TVar.  This may only be manipulated when holding that
+ * TVar's lock.  In particular, when a thread is putting itself to
+ * sleep, it mustn't release the TVar's lock until it has added itself
+ * to the wait queue and marked its TSO as BlockedOnSTM -- this makes
+ * sure that other threads will know to wake it.
  *
  * ---------------------------------------------------------------------------*/
 
 #include "PosixSource.h"
 #include "Rts.h"
-#include "RtsFlags.h"
+
 #include "RtsUtils.h"
-#include "Storage.h"
 #include "Schedule.h"
-#include "SMP.h"
 #include "STM.h"
 #include "Trace.h"
+#include "Threads.h"
 
-#include <stdlib.h>
 #include <stdio.h>
 
 #define TRUE 1
@@ -306,7 +305,7 @@ static StgClosure *lock_tvar(StgTRecHeader *trec,
   do {
     do {
       result = s -> current_value;
-    } while (GET_INFO(result) == &stg_TREC_HEADER_info);
+    } while (GET_INFO(UNTAG_CLOSURE(result)) == &stg_TREC_HEADER_info);
   } while (cas((void *)&(s -> current_value),
               (StgWord)result, (StgWord)trec) != (StgWord)result);
   return result;
@@ -388,10 +387,18 @@ static void unpark_tso(Capability *cap, StgTSO *tso) {
 
 static void unpark_waiters_on(Capability *cap, StgTVar *s) {
   StgTVarWatchQueue *q;
+  StgTVarWatchQueue *trail;
   TRACE("unpark_waiters_on tvar=%p", s);
-  for (q = s -> first_watch_queue_entry; 
-       q != END_STM_WATCH_QUEUE; 
+  // unblock TSOs in reverse order, to be a bit fairer (#2319)
+  for (q = s -> first_watch_queue_entry, trail = q;
+       q != END_STM_WATCH_QUEUE;
        q = q -> next_queue_entry) {
+    trail = q;
+  }
+  q = trail;
+  for (;
+       q != END_STM_WATCH_QUEUE; 
+       q = q -> prev_queue_entry) {
     if (watcher_is_tso(q)) {
       unpark_tso(cap, (StgTSO *)(q -> closure));
     }
@@ -1565,7 +1572,7 @@ static StgClosure *read_current_value(StgTRecHeader *trec STG_UNUSED, StgTVar *t
   result = tvar -> current_value;
 
 #if defined(STM_FG_LOCKS)
-  while (GET_INFO(result) == &stg_TREC_HEADER_info) {
+  while (GET_INFO(UNTAG_CLOSURE(result)) == &stg_TREC_HEADER_info) {
     TRACE("%p : read_current_value(%p) saw %p", trec, tvar, result);
     result = tvar -> current_value;
   }
@@ -1580,7 +1587,7 @@ static StgClosure *read_current_value(StgTRecHeader *trec STG_UNUSED, StgTVar *t
 StgClosure *stmReadTVar(Capability *cap,
                         StgTRecHeader *trec, 
                        StgTVar *tvar) {
-  StgTRecHeader *entry_in;
+  StgTRecHeader *entry_in = NULL;
   StgClosure *result = NULL;
   TRecEntry *entry = NULL;
   TRACE("%p : stmReadTVar(%p)", trec, tvar);
@@ -1623,7 +1630,7 @@ void stmWriteTVar(Capability *cap,
                  StgTVar *tvar, 
                  StgClosure *new_value) {
 
-  StgTRecHeader *entry_in;
+  StgTRecHeader *entry_in = NULL;
   TRecEntry *entry = NULL;
   TRACE("%p : stmWriteTVar(%p, %p)", trec, tvar, new_value);
   ASSERT (trec != NO_TREC);