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
