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