New implementation of BLACKHOLEs
[ghc-hetmet.git] / rts / Updates.h
index abca788..de9276c 100644 (file)
 #ifndef UPDATES_H
 #define UPDATES_H
 
-/* -----------------------------------------------------------------------------
-   Updates
-
-   We have two layers of update macros.  The top layer, UPD_IND() and
-   friends perform all the work of an update.  In detail:
-
-      - if the closure being updated is a blocking queue, then all the
-        threads waiting on the blocking queue are updated.
-
-      - then the lower level updateWithIndirection() macro is invoked 
-        to actually replace the closure with an indirection (see below).
-
-   -------------------------------------------------------------------------- */
-
-#ifdef TICKY_TICKY
-# define UPD_IND(updclosure, heapptr) \
-   UPD_PERM_IND(updclosure,heapptr)
-# define UPD_SPEC_IND(updclosure, ind_info, heapptr, and_then) \
-   UPD_PERM_IND(updclosure,heapptr); and_then
-#else
-#  define SEMI ;
-# define UPD_IND(updclosure, heapptr) \
-   UPD_REAL_IND(updclosure,INFO_PTR(stg_IND_info),heapptr,SEMI)
-# define UPD_SPEC_IND(updclosure, ind_info, heapptr, and_then) \
-   UPD_REAL_IND(updclosure,ind_info,heapptr,and_then)
-#endif
-
-/* These macros have to work in both C and C--, so here's the
- * impedence matching:
- */
-#ifdef CMINUSMINUS
-#define BLOCK_BEGIN
-#define BLOCK_END
-#define DECLARE_IPTR(info)  W_ info
-#define FCALL               foreign "C"
-#define INFO_PTR(info)      info
-#define ARG_PTR             "ptr"
-#else
-#define BLOCK_BEGIN         {
-#define BLOCK_END           }
-#define DECLARE_IPTR(info)  const StgInfoTable *(info)
-#define FCALL               /* nothing */
-#define INFO_PTR(info)      &info
-#define StgBlockingQueue_blocking_queue(closure) \
-    (((StgBlockingQueue *)closure)->blocking_queue)
-#define ARG_PTR             /* nothing */
-#endif
-
-/* UPD_IND actually does a PERM_IND if TICKY_TICKY is on;
-   if you *really* need an IND use UPD_REAL_IND
- */
-#define UPD_REAL_IND(updclosure, ind_info, heapptr, and_then)  \
-        BLOCK_BEGIN                                            \
-       DECLARE_IPTR(info);                                     \
-       info = GET_INFO(updclosure);                            \
-       updateWithIndirection(ind_info,                         \
-                             updclosure,                       \
-                             heapptr,                          \
-                             and_then);                        \
-       BLOCK_END
-
-#if defined(PROFILING) || defined(TICKY_TICKY)
-#define UPD_PERM_IND(updclosure, heapptr)      \
-        BLOCK_BEGIN                            \
-       updateWithPermIndirection(updclosure,   \
-                                 heapptr);     \
-       BLOCK_END
-#endif
-
-#if defined(RTS_SUPPORTS_THREADS)
-
-# ifdef TICKY_TICKY
-#  define UPD_IND_NOLOCK(updclosure, heapptr)  \
-        BLOCK_BEGIN                            \
-       updateWithPermIndirection(updclosure,   \
-                                 heapptr);     \
-       BLOCK_END
-# else
-#  define UPD_IND_NOLOCK(updclosure, heapptr)                  \
-        BLOCK_BEGIN                                            \
-       updateWithIndirection(INFO_PTR(stg_IND_info),           \
-                             updclosure,                       \
-                             heapptr,);                        \
-       BLOCK_END
-# endif
-
-#else
-#define UPD_IND_NOLOCK(updclosure,heapptr) UPD_IND(updclosure,heapptr)
+#ifndef CMINUSMINUS
+BEGIN_RTS_PRIVATE
 #endif
 
 /* -----------------------------------------------------------------------------
-   Awaken any threads waiting on a blocking queue (BLACKHOLE_BQ).
-   -------------------------------------------------------------------------- */
-
-#if defined(PAR) 
-
-/* 
-   In a parallel setup several types of closures might have a blocking queue:
-     BLACKHOLE_BQ ... same as in the default concurrent setup; it will be
-                      reawakened via calling UPD_IND on that closure after
-                     having finished the computation of the graph
-     FETCH_ME_BQ  ... a global indirection (FETCH_ME) may be entered by a 
-                      local TSO, turning it into a FETCH_ME_BQ; it will be
-                     reawakened via calling processResume
-     RBH          ... a revertible black hole may be entered by another 
-                      local TSO, putting it onto its blocking queue; since
-                     RBHs only exist while the corresponding closure is in 
-                     transit, they will be reawakened via calling 
-                     convertToFetchMe (upon processing an ACK message)
-
-   In a parallel setup a blocking queue may contain 3 types of closures:
-     TSO           ... as in the default concurrent setup
-     BLOCKED_FETCH ... indicating that a TSO on another PE is waiting for
-                       the result of the current computation
-     CONSTR        ... an RBHSave closure (which contains data ripped out of
-                       the closure to make room for a blocking queue; since
-                      it only contains data we use the exisiting type of
-                      a CONSTR closure); this closure is the end of a 
-                      blocking queue for an RBH closure; it only exists in
-                      this kind of blocking queue and must be at the end
-                      of the queue
-*/                   
-extern void awakenBlockedQueue(StgBlockingQueueElement *q, StgClosure *node);
-#define DO_AWAKEN_BQ(bqe, node)  STGCALL2(awakenBlockedQueue, bqe, node);
-
-#define AWAKEN_BQ(info,closure)                                                \
-       if (info == &stg_BLACKHOLE_BQ_info ||               \
-           info == &stg_FETCH_ME_BQ_info ||                \
-           get_itbl(closure)->type == RBH) {                           \
-               DO_AWAKEN_BQ(((StgBlockingQueue *)closure)->blocking_queue, closure);                           \
-       }
-
-#elif defined(GRAN)
-
-extern void awakenBlockedQueue(StgBlockingQueueElement *q, StgClosure *node);
-#define DO_AWAKEN_BQ(bq, node)  STGCALL2(awakenBlockedQueue, bq, node);
-
-/* In GranSim we don't have FETCH_ME or FETCH_ME_BQ closures, so they are
-   not checked. The rest of the code is the same as for GUM.
-*/
-#define AWAKEN_BQ(info,closure)                                                \
-       if (info == &stg_BLACKHOLE_BQ_info ||               \
-           get_itbl(closure)->type == RBH) {                           \
-               DO_AWAKEN_BQ(((StgBlockingQueue *)closure)->blocking_queue, closure);                           \
-       }
-
-#endif /* GRAN || PAR */
-
-
-/* -----------------------------------------------------------------------------
-   Updates: lower-level macros which update a closure with an
-   indirection to another closure.
-
-   There are several variants of this code.
-
-       PROFILING:
+   Updates
    -------------------------------------------------------------------------- */
 
 /* LDV profiling:
@@ -198,8 +48,7 @@ extern void awakenBlockedQueue(StgBlockingQueueElement *q, StgClosure *node);
   W_ sz;                                                               \
   W_ i;                                                                        \
   inf = %GET_STD_INFO(p);                                              \
-  if (%INFO_TYPE(inf) != HALF_W_(BLACKHOLE)                            \
-       && %INFO_TYPE(inf) != HALF_W_(CAF_BLACKHOLE)) {                 \
+  if (%INFO_TYPE(inf) != HALF_W_(BLACKHOLE)) {                         \
       if (%INFO_TYPE(inf) == HALF_W_(THUNK_SELECTOR)) {                        \
          sz = BYTES_TO_WDS(SIZEOF_StgSelector_NoThunkHdr);             \
      } else {                                                          \
@@ -232,7 +81,6 @@ FILL_SLOP(StgClosure *p)
 
     switch (inf->type) {
     case BLACKHOLE:
-    case CAF_BLACKHOLE:
        goto no_slop;
        // we already filled in the slop when we overwrote the thunk
        // with BLACKHOLE, and also an evacuated BLACKHOLE is only the
@@ -276,94 +124,56 @@ no_slop:
  * invert the optimisation.  Grrrr --SDM).
  */
 #ifdef CMINUSMINUS
-#define generation(n) (W_[generations] + n*SIZEOF_generation)
-#define updateWithIndirection(ind_info, p1, p2, and_then)      \
+
+#define updateWithIndirection(p1, p2, and_then)        \
     W_ bd;                                                     \
                                                                \
     DEBUG_FILL_SLOP(p1);                                       \
     LDV_RECORD_DEAD_FILL_SLOP_DYNAMIC(p1);                     \
     StgInd_indirectee(p1) = p2;                                        \
     prim %write_barrier() [];                                  \
+    SET_INFO(p1, stg_BLACKHOLE_info);                           \
+    LDV_RECORD_CREATE(p1);                                      \
     bd = Bdescr(p1);                                           \
-    if (bdescr_gen_no(bd) != 0 :: CInt) {                      \
+    if (bdescr_gen_no(bd) != 0 :: bits16) {                    \
       recordMutableCap(p1, TO_W_(bdescr_gen_no(bd)), R1);      \
-      SET_INFO(p1, stg_IND_OLDGEN_info);                       \
-      LDV_RECORD_CREATE(p1);                                   \
       TICK_UPD_OLD_IND();                                      \
       and_then;                                                        \
     } else {                                                   \
-      SET_INFO(p1, ind_info);                                  \
-      LDV_RECORD_CREATE(p1);                                   \
       TICK_UPD_NEW_IND();                                      \
       and_then;                                                        \
   }
-#else
-#define updateWithIndirection(ind_info, p1, p2, and_then)      \
-  {                                                            \
-    bdescr *bd;                                                        \
-                                                               \
-    /* cas(p1, 0, &stg_WHITEHOLE_info); */                     \
-    ASSERT( (P_)p1 != (P_)p2 && !closure_IND(p1) );            \
-    DEBUG_FILL_SLOP(p1);                                       \
-    LDV_RECORD_DEAD_FILL_SLOP_DYNAMIC(p1);                     \
-    ((StgInd *)p1)->indirectee = p2;                           \
-    write_barrier();                                           \
-    bd = Bdescr((P_)p1);                                       \
-    if (bd->gen_no != 0) {                                     \
-      recordMutableGenLock(p1, &generations[bd->gen_no]);      \
-      SET_INFO(p1, &stg_IND_OLDGEN_info);                      \
-      TICK_UPD_OLD_IND();                                      \
-      and_then;                                                        \
-    } else {                                                   \
-      SET_INFO(p1, ind_info);                                  \
-      LDV_RECORD_CREATE(p1);                                   \
-      TICK_UPD_NEW_IND();                                      \
-      and_then;                                                        \
-    }                                                          \
-  }
-#endif
 
-/* The permanent indirection version isn't performance critical.  We
- * therefore use an inline C function instead of the C-- macro.
- */
-#ifndef CMINUSMINUS
-INLINE_HEADER void
-updateWithPermIndirection(StgClosure *p1,
-                         StgClosure *p2) 
-{
-  bdescr *bd;
-
-  ASSERT( p1 != p2 && !closure_IND(p1) );
-
-  /*
-   * @LDV profiling
-   * Destroy the old closure.
-   * Nb: LDV_* stuff cannot mix with ticky-ticky
-   */
-  LDV_RECORD_DEAD_FILL_SLOP_DYNAMIC(p1);
+#else /* !CMINUSMINUS */
 
-  bd = Bdescr((P_)p1);
-  if (bd->gen_no != 0) {
-    recordMutableGenLock(p1, &generations[bd->gen_no]);
-    ((StgInd *)p1)->indirectee = p2;
-    SET_INFO(p1, &stg_IND_OLDGEN_PERM_info);
-    /*
-     * @LDV profiling
-     * We have just created a new closure.
-     */
-    LDV_RECORD_CREATE(p1);
-    TICK_UPD_OLD_PERM_IND();
-  } else {
+INLINE_HEADER void updateWithIndirection (Capability *cap, 
+                                          StgClosure *p1, 
+                                          StgClosure *p2)
+{
+    bdescr *bd;
+    
+    ASSERT( (P_)p1 != (P_)p2 );
+    /* not necessarily true: ASSERT( !closure_IND(p1) ); */
+    /* occurs in RaiseAsync.c:raiseAsync() */
+    DEBUG_FILL_SLOP(p1);
+    LDV_RECORD_DEAD_FILL_SLOP_DYNAMIC(p1);
     ((StgInd *)p1)->indirectee = p2;
-    SET_INFO(p1, &stg_IND_PERM_info);
-    /*
-     * @LDV profiling
-     * We have just created a new closure.
-     */
+    write_barrier();
+    SET_INFO(p1, &stg_BLACKHOLE_info);
     LDV_RECORD_CREATE(p1);
-    TICK_UPD_NEW_PERM_IND(p1);
-  }
+    bd = Bdescr((StgPtr)p1);
+    if (bd->gen_no != 0) {
+        recordMutableCap(p1, cap, bd->gen_no);
+        TICK_UPD_OLD_IND();
+    } else {
+        TICK_UPD_NEW_IND();
+    }
 }
+
+#endif /* CMINUSMINUS */
+
+#ifndef CMINUSMINUS
+END_RTS_PRIVATE
 #endif
 
 #endif /* UPDATES_H */