<div dir="ltr"><div>Hi Omer,</div><div><br></div><div>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. <br></div><div><br></div><div>Definition of stg_raise:<br></div><div><a href="https://github.com/ghc/ghc/blob/ba5797937e575ce6119de6c07703e90dda2557e8/rts/Exception.cmm#L424-L427">https://github.com/ghc/ghc/blob/ba5797937e575ce6119de6c07703e90dda2557e8/rts/Exception.cmm#L424-L427</a></div><div><br></div><div>raiseExceptionHelper dealing with update frames:</div><div><a href="https://github.com/ghc/ghc/blob/d9d463289fe20316cff12a8f0dbf414db678fa72/rts/Schedule.c#L2864-L2875">https://github.com/ghc/ghc/blob/d9d463289fe20316cff12a8f0dbf414db678fa72/rts/Schedule.c#L2864-L2875</a></div><div><br></div><div>In general, yes, you can think that a BLACKHOLE will point to a non-THUNK object assuming that everything went right.<br></div><div><br></div><div>Hope that helps,</div><div>Rahul<br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Mar 23, 2018 at 5:48 PM, Ö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">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 BLACKHOLE<br>
whereas in the latter we have and the blocking queue holds all those blocked<br>
threads. Did I get this right?<br>
<br>
Secondly, can a BLACKHOLE point to a THUNK? I'd expect no, because we BLACKHOLE<br>
a closure when we're done evaluating it (assuming no eager blackholing), and<br>
evaluation usually happens up to WHNF.<br>
<br>
Thanks,<br>
<br>
Ömer<br>
<div class="HOEnZb"><div class="h5"><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>> wrote:<br>
>>><br>
>>> Hi,<br>
>>><br>
>>> I've been looking at BLACKHOLE closures and how the indirectee field 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, 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 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 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) = 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 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 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 indirectee<br>
>> and see the IND. But this state can't be observed by the GC, because 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>
</div></div></blockquote></div><br><br clear="all"><br>-- <br><div class="gmail_signature" data-smartmail="gmail_signature">Rahul Muttineni</div>
</div>