diff options
author | Simon Marlow <marlowsd@gmail.com> | 2011-01-27 16:42:26 +0000 |
---|---|---|
committer | Simon Marlow <marlowsd@gmail.com> | 2011-01-27 16:42:26 +0000 |
commit | 784e214dd44eba39f4c34936a27e6cc82948205c (patch) | |
tree | 42ce7135e1045117461118f7cbc098df5e707138 /rts/Messages.c | |
parent | 069cd16951bd45a55c94b5adce048c4ec9aad2c8 (diff) | |
download | haskell-784e214dd44eba39f4c34936a27e6cc82948205c.tar.gz |
Annotate thread stop events with the owner of the black hole
So we can now get these in ThreadScope:
19487000: cap 1: stopping thread 6 (blocked on black hole owned by thread 4)
Note: needs an update to ghc-events. Older ThreadScopes will just
ignore the new information.
Diffstat (limited to 'rts/Messages.c')
-rw-r--r-- | rts/Messages.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/rts/Messages.c b/rts/Messages.c index 1730278930..5dec6c6927 100644 --- a/rts/Messages.c +++ b/rts/Messages.c @@ -303,3 +303,46 @@ loop: return 0; // not blocked } +// A shorter version of messageBlackHole(), that just returns the +// owner (or NULL if the owner cannot be found, because the blackhole +// has been updated in the meantime). + +StgTSO * blackHoleOwner (StgClosure *bh) +{ + const StgInfoTable *info; + StgClosure *p; + + info = bh->header.info; + + if (info != &stg_BLACKHOLE_info && + info != &stg_CAF_BLACKHOLE_info && + info != &__stg_EAGER_BLACKHOLE_info && + info != &stg_WHITEHOLE_info) { + return NULL; + } + + // The blackhole must indirect to a TSO, a BLOCKING_QUEUE, an IND, + // or a value. +loop: + // NB. VOLATILE_LOAD(), because otherwise gcc hoists the load + // and turns this into an infinite loop. + p = UNTAG_CLOSURE((StgClosure*)VOLATILE_LOAD(&((StgInd*)bh)->indirectee)); + info = p->header.info; + + if (info == &stg_IND_info) goto loop; + + else if (info == &stg_TSO_info) + { + return (StgTSO*)p; + } + else if (info == &stg_BLOCKING_QUEUE_CLEAN_info || + info == &stg_BLOCKING_QUEUE_DIRTY_info) + { + StgBlockingQueue *bq = (StgBlockingQueue *)p; + return bq->owner; + } + + return NULL; // not blocked +} + + |