Wrap gcc on Windows, to provide the -B flags
[ghc-hetmet.git] / rts / ThreadPaused.c
index f701704..58c30e3 100644 (file)
@@ -6,12 +6,14 @@
  *
  * ---------------------------------------------------------------------------*/
 
+// #include "PosixSource.h"
 #include "Rts.h"
-#include "Storage.h"
+
+#include "ThreadPaused.h"
+#include "sm/Storage.h"
 #include "Updates.h"
 #include "RaiseAsync.h"
 #include "Trace.h"
-#include "RtsFlags.h"
 
 #include <string.h> // for memmove()
 
@@ -49,7 +51,7 @@ stackSqueeze(StgTSO *tso, StgPtr bottom)
     current_gap_size = 0;
     gap = (struct stack_gap *) (tso->sp - sizeofW(StgUpdateFrame));
 
-    while (frame < bottom) {
+    while (frame <= bottom) {
        
        info = get_ret_itbl((StgClosure *)frame);
        switch (info->i.type) {
@@ -73,7 +75,7 @@ stackSqueeze(StgTSO *tso, StgPtr bottom)
                 * screw us up if we don't check.
                 */
                if (upd->updatee != updatee && !closure_IND(upd->updatee)) {
-                   UPD_IND_NOLOCK(upd->updatee, updatee);
+                   UPD_IND(upd->updatee, updatee);
                }
 
                // now mark this update frame as a stack gap.  The gap
@@ -140,23 +142,23 @@ stackSqueeze(StgTSO *tso, StgPtr bottom)
     // <empty> indicates unused
     //
     {
-       void *sp;
-       void *gap_start, *next_gap_start, *gap_end;
+       StgWord8 *sp;
+       StgWord8 *gap_start, *next_gap_start, *gap_end;
        nat chunk_size;
 
-       next_gap_start = (void *)((unsigned char*)gap + sizeof(StgUpdateFrame));
+       next_gap_start = (StgWord8*)gap + sizeof(StgUpdateFrame);
        sp = next_gap_start;
 
        while ((StgPtr)gap > tso->sp) {
 
            // we're working in *bytes* now...
            gap_start = next_gap_start;
-           gap_end = (void*) ((unsigned char*)gap_start - gap->gap_size * sizeof(W_));
+           gap_end = gap_start - gap->gap_size * sizeof(W_);
 
            gap = gap->next_gap;
-           next_gap_start = (void *)((unsigned char*)gap + sizeof(StgUpdateFrame));
+           next_gap_start = (StgWord8*)gap + sizeof(StgUpdateFrame);
 
-           chunk_size = (unsigned char*)gap_end - (unsigned char*)next_gap_start;
+           chunk_size = gap_end - next_gap_start;
            sp -= chunk_size;
            memmove(sp, next_gap_start, chunk_size);
        }
@@ -177,6 +179,8 @@ threadPaused(Capability *cap, StgTSO *tso)
 {
     StgClosure *frame;
     StgRetInfoTable *info;
+    const StgInfoTable *bh_info;
+    const StgInfoTable *cur_bh_info USED_IF_THREADS;
     StgClosure *bh;
     StgPtr stack_end;
     nat words_to_squeeze = 0;
@@ -192,6 +196,10 @@ threadPaused(Capability *cap, StgTSO *tso)
     maybePerformBlockedException (cap, tso);
     if (tso->what_next == ThreadKilled) { return; }
 
+    // NB. Blackholing is *not* optional, we must either do lazy
+    // blackholing, or eager blackholing consistently.  See Note
+    // [upd-black-hole] in sm/Scav.c.
+
     stack_end = &tso->stack[tso->stack_size];
     
     frame = (StgClosure *)tso->sp;
@@ -199,6 +207,11 @@ threadPaused(Capability *cap, StgTSO *tso)
     while (1) {
        // If we've already marked this frame, then stop here.
        if (frame->header.info == (StgInfoTable *)&stg_marked_upd_frame_info) {
+           if (prev_was_update_frame) {
+               words_to_squeeze += sizeofW(StgUpdateFrame);
+               weight += weight_pending;
+               weight_pending = 0;
+           }
            goto end;
        }
 
@@ -211,15 +224,22 @@ threadPaused(Capability *cap, StgTSO *tso)
            SET_INFO(frame, (StgInfoTable *)&stg_marked_upd_frame_info);
 
            bh = ((StgUpdateFrame *)frame)->updatee;
+            bh_info = bh->header.info;
 
-           if (closure_IND(bh) || bh->header.info == &stg_BLACKHOLE_info) {
+#ifdef THREADED_RTS
+        retry:
+#endif
+           if (closure_flags[INFO_PTR_TO_STRUCT(bh_info)->type] & _IND
+                || bh_info == &stg_BLACKHOLE_info) {
                debugTrace(DEBUG_squeeze,
                           "suspending duplicate work: %ld words of stack",
                           (long)((StgPtr)frame - tso->sp));
 
                // If this closure is already an indirection, then
-               // suspend the computation up to this point:
-               suspendComputation(cap,tso,(StgPtr)frame);
+               // suspend the computation up to this point.
+               // NB. check raiseAsync() to see what happens when
+               // we're in a loop (#2783).
+               suspendComputation(cap,tso,(StgUpdateFrame*)frame);
 
                // Now drop the update frame, and arrange to return
                // the value to the frame underneath:
@@ -229,14 +249,12 @@ threadPaused(Capability *cap, StgTSO *tso)
 
                // And continue with threadPaused; there might be
                // yet more computation to suspend.
-               threadPaused(cap,tso);
-               return;
+                frame = (StgClosure *)tso->sp + 2;
+                prev_was_update_frame = rtsFalse;
+                continue;
            }
 
            if (bh->header.info != &stg_CAF_BLACKHOLE_info) {
-#if (!defined(LAZY_BLACKHOLING)) && defined(DEBUG)
-               debugBelch("Unexpected lazy BHing required at 0x%04lx\n",(long)bh);
-#endif
                // zero out the slop so that the sanity checker can tell
                // where the next closure is.
                DEBUG_FILL_SLOP(bh);
@@ -245,7 +263,20 @@ threadPaused(Capability *cap, StgTSO *tso)
                // We pretend that bh is now dead.
                LDV_recordDead_FILL_SLOP_DYNAMIC((StgClosure *)bh);
 #endif
+                // an EAGER_BLACKHOLE gets turned into a BLACKHOLE here.
+#ifdef THREADED_RTS
+                cur_bh_info = (const StgInfoTable *)
+                    cas((StgVolatilePtr)&bh->header.info, 
+                        (StgWord)bh_info, 
+                        (StgWord)&stg_BLACKHOLE_info);
+
+                if (cur_bh_info != bh_info) {
+                    bh_info = cur_bh_info;
+                    goto retry;
+                }
+#else
                SET_INFO(bh,&stg_BLACKHOLE_info);
+#endif
 
                // We pretend that bh has just been created.
                LDV_RECORD_CREATE(bh);
@@ -284,7 +315,7 @@ end:
     // the number of words we have to shift down is less than the
     // number of stack words we squeeze away by doing so.
     if (RtsFlags.GcFlags.squeezeUpdFrames == rtsTrue &&
-       weight < words_to_squeeze) {
+       ((weight <= 5 && words_to_squeeze > 0) || weight < words_to_squeeze)) {
        stackSqueeze(tso, (StgPtr)frame);
     }
 }