/* -----------------------------------------------------------------------------
- * $Id: Updates.h,v 1.7 1999/02/05 16:02:31 simonm Exp $
+ * $Id: Updates.h,v 1.18 2000/05/15 14:38:11 simonmar Exp $
*
* (c) The GHC Team, 1998-1999
*
* preferably don't use this macro inline in compiled code.
*/
-#define UPD_IND(updclosure, heapptr) \
- AWAKEN_BQ(updclosure); \
- updateWithIndirection((StgClosure *)updclosure, \
- (StgClosure *)heapptr);
+#ifdef TICKY_TICKY
+# define UPD_IND(updclosure, heapptr) UPD_PERM_IND(updclosure,heapptr)
+#else
+# define UPD_IND(updclosure, heapptr) UPD_REAL_IND(updclosure,heapptr)
+#endif
+
+/* UPD_IND actually does a PERM_IND if TICKY_TICKY is on;
+ if you *really* need an IND use UPD_REAL_IND
+ */
+#ifdef SMP
+#define UPD_REAL_IND(updclosure, heapptr) \
+ { \
+ const StgInfoTable *info; \
+ if (Bdescr((P_)updclosure)->back != (bdescr *)BaseReg) { \
+ info = LOCK_CLOSURE(updclosure); \
+ } else { \
+ info = updclosure->header.info; \
+ } \
+ AWAKEN_BQ(info,updclosure); \
+ updateWithIndirection(info, \
+ (StgClosure *)updclosure, \
+ (StgClosure *)heapptr); \
+ }
+#else
+#define UPD_REAL_IND(updclosure, heapptr) \
+ { \
+ const StgInfoTable *info; \
+ info = ((StgClosure *)updclosure)->header.info; \
+ AWAKEN_BQ(info,updclosure); \
+ updateWithIndirection(info, \
+ (StgClosure *)updclosure, \
+ (StgClosure *)heapptr); \
+ }
+#endif
+
+#if defined(PROFILING) || defined(TICKY_TICKY)
+#define UPD_PERM_IND(updclosure, heapptr) \
+ { \
+ const StgInfoTable *info; \
+ info = ((StgClosure *)updclosure)->header.info; \
+ AWAKEN_BQ(info,updclosure); \
+ updateWithPermIndirection(info, \
+ (StgClosure *)updclosure, \
+ (StgClosure *)heapptr); \
+ }
+#endif
+
+#ifdef SMP
+#define UPD_IND_NOLOCK(updclosure, heapptr) \
+ { \
+ const StgInfoTable *info; \
+ info = updclosure->header.info; \
+ AWAKEN_BQ(info,updclosure); \
+ updateWithIndirection(info, \
+ (StgClosure *)updclosure, \
+ (StgClosure *)heapptr); \
+ }
+#else
+#define UPD_IND_NOLOCK(updclosure,heapptr) UPD_IND(updclosure,heapptr)
+#endif
/* -----------------------------------------------------------------------------
Awaken any threads waiting on this computation
-------------------------------------------------------------------------- */
-extern void awaken_blocked_queue(StgTSO *q);
+#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 ... a 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 == &BLACKHOLE_BQ_info || \
+ info == &FETCH_ME_BQ_info || \
+ get_itbl(closure)->type == RBH) { \
+ StgBlockingQueueElement *bqe = ((StgBlockingQueue *)closure)->blocking_queue;\
+ ASSERT(bqe!=END_BQ_QUEUE); \
+ DO_AWAKEN_BQ(bqe, closure); \
+ }
-#define AWAKEN_BQ(closure) \
- if (closure->header.info == &BLACKHOLE_BQ_info) { \
- StgTSO *bq = ((StgBlockingQueue *)closure)->blocking_queue;\
- if (bq != (StgTSO *)&END_TSO_QUEUE_closure) { \
- STGCALL1(awaken_blocked_queue, bq); \
- } \
+#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 == &BLACKHOLE_BQ_info || \
+ get_itbl(closure)->type == RBH) { \
+ StgBlockingQueueElement *bqe = ((StgBlockingQueue *)closure)->blocking_queue;\
+ ASSERT(bqe!=END_BQ_QUEUE); \
+ DO_AWAKEN_BQ(bqe, closure); \
}
-/* -----------------------------------------------------------------------------
+#else /* !GRAN && !PAR */
+
+extern void awakenBlockedQueue(StgTSO *q);
+#define DO_AWAKEN_BQ(closure) \
+ STGCALL1(awakenBlockedQueue, \
+ ((StgBlockingQueue *)closure)->blocking_queue);
+
+#define AWAKEN_BQ(info,closure) \
+ if (info == &BLACKHOLE_BQ_info) { \
+ DO_AWAKEN_BQ(closure); \
+ }
+
+#endif /* GRAN || PAR */
+
+/* -------------------------------------------------------------------------
Push an update frame on the stack.
- -------------------------------------------------------------------------- */
+ ------------------------------------------------------------------------- */
#if defined(PROFILING)
#define PUSH_STD_CCCS(frame) frame->header.prof.ccs = CCCS
#define PUSH_STD_CCCS(frame)
#endif
-extern const StgPolyInfoTable Upd_frame_info;
+extern DLL_IMPORT_DATA const StgPolyInfoTable upd_frame_info;
#define PUSH_UPD_FRAME(target, Sp_offset) \
{ \
StgUpdateFrame *__frame; \
- TICK_UPDF_PUSHED(); \
- __frame = stgCast(StgUpdateFrame*,Sp + (Sp_offset)) - 1; \
- SET_INFO(__frame,stgCast(StgInfoTable*,&Upd_frame_info)); \
+ TICK_UPDF_PUSHED(target, GET_INFO((StgClosure*)target)); \
+ __frame = (StgUpdateFrame *)(Sp + (Sp_offset)) - 1; \
+ SET_INFO(__frame, (StgInfoTable *)&upd_frame_info); \
__frame->link = Su; \
__frame->updatee = (StgClosure *)(target); \
PUSH_STD_CCCS(__frame); \
extern void newCAF(StgClosure*);
-#define UPD_CAF(cafptr, bhptr) \
- { \
- SET_INFO((StgInd *)cafptr,&IND_STATIC_info); \
- ((StgInd *)cafptr)->indirectee = (StgClosure *)(bhptr); \
- STGCALL1(newCAF,(StgClosure *)cafptr); \
+/* newCAF must be called before the itbl ptr is overwritten, since
+ newCAF records the old itbl ptr in order to do CAF reverting
+ (which Hugs needs to do in order that combined mode works right.)
+*/
+#define UPD_CAF(cafptr, bhptr) \
+ { \
+ LOCK_CLOSURE(cafptr); \
+ STGCALL1(newCAF,(StgClosure *)cafptr); \
+ ((StgInd *)cafptr)->indirectee = (StgClosure *)(bhptr); \
+ SET_INFO((StgInd *)cafptr,(const StgInfoTable*)&IND_STATIC_info); \
}
+#ifdef INTERPRETER
+extern void newCAF_made_by_Hugs(StgCAF*);
+#endif
+
/* -----------------------------------------------------------------------------
Update-related prototypes
-------------------------------------------------------------------------- */
-extern STGFUN(Upd_frame_entry);
+DLL_IMPORT_RTS extern STGFUN(upd_frame_entry);
-extern const StgInfoTable PAP_info;
-STGFUN(PAP_entry);
+extern DLL_IMPORT_DATA const StgInfoTable PAP_info;
+DLL_IMPORT_RTS STGFUN(PAP_entry);
-EXTFUN(stg_update_PAP);
+EXTFUN_RTS(stg_update_PAP);
-extern const StgInfoTable AP_UPD_info;
-STGFUN(AP_UPD_entry);
+extern DLL_IMPORT_DATA const StgInfoTable AP_UPD_info;
+DLL_IMPORT_RTS STGFUN(AP_UPD_entry);
-extern const StgInfoTable raise_info;
+extern DLL_IMPORT_DATA const StgInfoTable raise_info;
#endif /* UPDATES_H */