Hi Rahul, I'm still confused. The code that walks the stack and updates UPDATE_FRAMEs only makes indirections point to the "raise" closure, not to thunks or anything else (I also don't understand why this is needed but I guess that's another topic). I still don't see how can a BLACKHOLE point to a THUNK.
Ömer 2018-03-23 18:51 GMT+03:00 Rahul Muttineni <[email protected]>: > Hi Omer, > > As per my understanding, a BLACKHOLE can point to a THUNK when an exception > is thrown. An exception walks up the stack and overwrites the blackholes > pointed to by the update frames as it walks with an stg_raise closure. That > way, if any concurrent thread happens to evaluate a thunk that was walked, > it'll evaluate the thunk which will blow up as well thereby throwing the > exception on the other thread(s) too. > > Definition of stg_raise: > https://github.com/ghc/ghc/blob/ba5797937e575ce6119de6c07703e90dda2557e8/rts/Exception.cmm#L424-L427 > > raiseExceptionHelper dealing with update frames: > https://github.com/ghc/ghc/blob/d9d463289fe20316cff12a8f0dbf414db678fa72/rts/Schedule.c#L2864-L2875 > > In general, yes, you can think that a BLACKHOLE will point to a non-THUNK > object assuming that everything went right. > > Hope that helps, > Rahul > > On Fri, Mar 23, 2018 at 5:48 PM, Ömer Sinan Ağacan <[email protected]> > wrote: >> >> Thanks Simon, that's really helpful. >> >> A few more questions: >> >> As far as I understand the difference between >> >> - BLACKHOLE pointing to a TSO >> - BLACKHOLE pointing to a BLOCKING_QUEUE >> >> is that in the former we don't yet have any threads blocked by the >> BLACKHOLE >> whereas in the latter we have and the blocking queue holds all those >> blocked >> threads. Did I get this right? >> >> Secondly, can a BLACKHOLE point to a THUNK? I'd expect no, because we >> BLACKHOLE >> a closure when we're done evaluating it (assuming no eager blackholing), >> and >> evaluation usually happens up to WHNF. >> >> Thanks, >> >> Ömer >> >> 2018-03-20 18:27 GMT+03:00 Simon Marlow <[email protected]>: >> > Added comments: https://phabricator.haskell.org/D4517 >> > >> > On 20 March 2018 at 14:58, Simon Marlow <[email protected]> wrote: >> >> >> >> Hi Omer, >> >> >> >> On 20 March 2018 at 13:05, Ömer Sinan Ağacan <[email protected]> >> >> wrote: >> >>> >> >>> Hi, >> >>> >> >>> I've been looking at BLACKHOLE closures and how the indirectee field >> >>> is >> >>> used >> >>> and I have a few questions: >> >>> >> >>> Looking at evacuate for BLACKHOLE closures: >> >>> >> >>> case BLACKHOLE: >> >>> { >> >>> StgClosure *r; >> >>> const StgInfoTable *i; >> >>> r = ((StgInd*)q)->indirectee; >> >>> if (GET_CLOSURE_TAG(r) == 0) { >> >>> i = r->header.info; >> >>> if (IS_FORWARDING_PTR(i)) { >> >>> r = (StgClosure *)UN_FORWARDING_PTR(i); >> >>> i = r->header.info; >> >>> } >> >>> if (i == &stg_TSO_info >> >>> || i == &stg_WHITEHOLE_info >> >>> || i == &stg_BLOCKING_QUEUE_CLEAN_info >> >>> || i == &stg_BLOCKING_QUEUE_DIRTY_info) { >> >>> copy(p,info,q,sizeofW(StgInd),gen_no); >> >>> return; >> >>> } >> >>> ASSERT(i != &stg_IND_info); >> >>> } >> >>> q = r; >> >>> *p = r; >> >>> goto loop; >> >>> } >> >>> >> >>> It seems like indirectee can be a TSO, WHITEHOLE, >> >>> BLOCKING_QUEUE_CLEAN, >> >>> BLOCKING_QUEUE_DIRTY, and it can't be IND. I'm wondering what does it >> >>> mean for >> >>> a BLACKHOLE to point to a >> >>> >> >>> - TSO >> >>> - WHITEHOLE >> >>> - BLOCKING_QUEUE_CLEAN >> >>> - BLOCKING_QUEUE_DIRTY >> >> >> >> >> >> That sounds right to me. >> >> >> >>> >> >>> Is this documented somewhere or otherwise could someone give a few >> >>> pointers on >> >>> where to look in the code? >> >> >> >> >> >> Unfortunately I don't think we have good documentation for this, but >> >> you >> >> should look at the comments around messageBlackHole in Messages.c. >> >> >> >>> >> >>> Secondly, I also looked at the BLACKHOLE entry code, and it seems like >> >>> it >> >>> has a >> >>> different assumption about what can indirectee field point to: >> >>> >> >>> INFO_TABLE(stg_BLACKHOLE,1,0,BLACKHOLE,"BLACKHOLE","BLACKHOLE") >> >>> (P_ node) >> >>> { >> >>> W_ r, info, owner, bd; >> >>> P_ p, bq, msg; >> >>> >> >>> TICK_ENT_DYN_IND(); /* tick */ >> >>> >> >>> retry: >> >>> p = StgInd_indirectee(node); >> >>> if (GETTAG(p) != 0) { >> >>> return (p); >> >>> } >> >>> >> >>> info = StgHeader_info(p); >> >>> if (info == stg_IND_info) { >> >>> // This could happen, if e.g. we got a BLOCKING_QUEUE that >> >>> has >> >>> // just been replaced with an IND by another thread in >> >>> // wakeBlockingQueue(). >> >>> goto retry; >> >>> } >> >>> >> >>> if (info == stg_TSO_info || >> >>> info == stg_BLOCKING_QUEUE_CLEAN_info || >> >>> info == stg_BLOCKING_QUEUE_DIRTY_info) >> >>> { >> >>> ("ptr" msg) = ccall allocate(MyCapability() "ptr", >> >>> >> >>> BYTES_TO_WDS(SIZEOF_MessageBlackHole)); >> >>> >> >>> SET_HDR(msg, stg_MSG_BLACKHOLE_info, CCS_SYSTEM); >> >>> MessageBlackHole_tso(msg) = CurrentTSO; >> >>> MessageBlackHole_bh(msg) = node; >> >>> >> >>> (r) = ccall messageBlackHole(MyCapability() "ptr", msg >> >>> "ptr"); >> >>> >> >>> if (r == 0) { >> >>> goto retry; >> >>> } else { >> >>> StgTSO_why_blocked(CurrentTSO) = >> >>> BlockedOnBlackHole::I16; >> >>> StgTSO_block_info(CurrentTSO) = msg; >> >>> jump stg_block_blackhole(node); >> >>> } >> >>> } >> >>> else >> >>> { >> >>> ENTER(p); >> >>> } >> >>> } >> >>> >> >>> The difference is, when the tag of indirectee is 0, evacuate assumes >> >>> that >> >>> indirectee can't point to an IND, but BLACKHOLE entry code thinks it's >> >>> possible >> >>> and there's even a comment about why. (I don't understand the comment >> >>> yet) I'm >> >>> wondering if this code is correct, and why. Again any pointers would >> >>> be >> >>> appreciated. >> >> >> >> >> >> Taking a quick look at the code, my guess is that: >> >> - a BLOCKING_QUEUE gets overwritten by an IND in wakeBlockingQueue() >> >> - but when this happens, the indirectee of the BLACKHOLE will also be >> >> overwritten to point to the value >> >> >> >> At runtime a thread might see an intermediate state because these >> >> mutations are happening in another thread, so we might follow the >> >> indirectee >> >> and see the IND. But this state can't be observed by the GC, because >> >> all >> >> mutator threads have stopped at a safe point. >> >> >> >> Cheers >> >> Simon >> >> >> >> >> >>> >> >>> Thanks, >> >>> >> >>> Ömer >> >>> _______________________________________________ >> >>> ghc-devs mailing list >> >>> [email protected] >> >>> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs >> >> >> >> >> > >> _______________________________________________ >> ghc-devs mailing list >> [email protected] >> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs > > > > > -- > Rahul Muttineni _______________________________________________ ghc-devs mailing list [email protected] http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
