X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=rts%2FUpdates.h;h=988fb6059fad04eeb0283a7609357bdae4810eb8;hb=6cf8982ac30be6836a0cdd8be5a6ac1a1a144213;hp=5872157c81be52eeb06c18fad205c2054dedbd12;hpb=0065d5ab628975892cea1ec7303f968c3338cbe1;p=ghc-hetmet.git diff --git a/rts/Updates.h b/rts/Updates.h index 5872157..988fb60 100644 --- a/rts/Updates.h +++ b/rts/Updates.h @@ -9,6 +9,10 @@ #ifndef UPDATES_H #define UPDATES_H +#ifndef CMINUSMINUS +BEGIN_RTS_PRIVATE +#endif + /* ----------------------------------------------------------------------------- Updates @@ -23,141 +27,43 @@ -------------------------------------------------------------------------- */ -#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: + * impedance 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 - */ +/* krc: there used to be an UPD_REAL_IND and an + UPD_PERM_IND, the latter of which was used for + ticky and cost-centre profiling. + for now, we just have 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) -#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. @@ -198,17 +104,20 @@ extern void awakenBlockedQueue(StgBlockingQueueElement *q, StgClosure *node); W_ sz; \ W_ i; \ inf = %GET_STD_INFO(p); \ - if (%INFO_TYPE(inf) != HALF_W_(THUNK_SELECTOR) \ - && %INFO_TYPE(inf) != HALF_W_(BLACKHOLE) \ + if (%INFO_TYPE(inf) != HALF_W_(BLACKHOLE) \ && %INFO_TYPE(inf) != HALF_W_(CAF_BLACKHOLE)) { \ - if (%INFO_TYPE(inf) == HALF_W_(AP_STACK)) { \ - sz = StgAP_STACK_size(p) + BYTES_TO_WDS(SIZEOF_StgAP_STACK_NoThunkHdr); \ - } else { \ - if (%INFO_TYPE(inf) == HALF_W_(AP)) { \ - sz = TO_W_(StgAP_n_args(p)) + BYTES_TO_WDS(SIZEOF_StgAP_NoThunkHdr); \ + if (%INFO_TYPE(inf) == HALF_W_(THUNK_SELECTOR)) { \ + sz = BYTES_TO_WDS(SIZEOF_StgSelector_NoThunkHdr); \ + } else { \ + if (%INFO_TYPE(inf) == HALF_W_(AP_STACK)) { \ + sz = StgAP_STACK_size(p) + BYTES_TO_WDS(SIZEOF_StgAP_STACK_NoThunkHdr); \ } else { \ - sz = TO_W_(%INFO_PTRS(inf)) + TO_W_(%INFO_NPTRS(inf)); \ - } \ + if (%INFO_TYPE(inf) == HALF_W_(AP)) { \ + sz = TO_W_(StgAP_n_args(p)) + BYTES_TO_WDS(SIZEOF_StgAP_NoThunkHdr); \ + } else { \ + sz = TO_W_(%INFO_PTRS(inf)) + TO_W_(%INFO_NPTRS(inf)); \ + } \ + } \ } \ i = 0; \ for: \ @@ -230,8 +139,13 @@ 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 + // size of an IND. case THUNK_SELECTOR: - return; + sz = sizeofW(StgSelector) - sizeofW(StgThunkHeader); + break; case AP: sz = ((StgAP *)p)->n_args + sizeofW(StgAP) - sizeofW(StgThunkHeader); break; @@ -245,6 +159,8 @@ FILL_SLOP(StgClosure *p) for (i = 0; i < sz; i++) { ((StgThunk *)p)->payload[i] = 0; } +no_slop: + ; } #endif /* CMINUSMINUS */ @@ -273,12 +189,10 @@ FILL_SLOP(StgClosure *p) DEBUG_FILL_SLOP(p1); \ LDV_RECORD_DEAD_FILL_SLOP_DYNAMIC(p1); \ StgInd_indirectee(p1) = p2; \ - foreign "C" wb() []; \ + prim %write_barrier() []; \ bd = Bdescr(p1); \ if (bdescr_gen_no(bd) != 0 :: CInt) { \ - foreign "C" recordMutableCap(p1 "ptr", \ - MyCapability() "ptr", \ - bdescr_gen_no(bd)) [R1]; \ + recordMutableCap(p1, TO_W_(bdescr_gen_no(bd)), R1); \ SET_INFO(p1, stg_IND_OLDGEN_info); \ LDV_RECORD_CREATE(p1); \ TICK_UPD_OLD_IND(); \ @@ -290,72 +204,34 @@ FILL_SLOP(StgClosure *p) 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; \ - wb(); \ - 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; \ - } \ +#define updateWithIndirection(ind_info, p1, p2, and_then) \ + { \ + 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; \ + write_barrier(); \ + bd = Bdescr((P_)p1); \ + if (bd->gen_no != 0) { \ + recordMutableGenLock(p1, 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 +#endif /* CMINUSMINUS */ -/* 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); - - 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 { - ((StgInd *)p1)->indirectee = p2; - SET_INFO(p1, &stg_IND_PERM_info); - /* - * @LDV profiling - * We have just created a new closure. - */ - LDV_RECORD_CREATE(p1); - TICK_UPD_NEW_PERM_IND(p1); - } -} +END_RTS_PRIVATE #endif #endif /* UPDATES_H */