Question about indirectees of BLACKHOLE closures

Ömer Sinan Ağacan omeragacan at gmail.com
Tue Mar 20 13:05:25 UTC 2018


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

Is this documented somewhere or otherwise could someone give a few pointers on
where to look in the code?

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.

Thanks,

Ömer


More information about the ghc-devs mailing list