summaryrefslogtreecommitdiff
path: root/rts/Messages.c
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2011-01-27 16:42:26 +0000
committerSimon Marlow <marlowsd@gmail.com>2011-01-27 16:42:26 +0000
commit784e214dd44eba39f4c34936a27e6cc82948205c (patch)
tree42ce7135e1045117461118f7cbc098df5e707138 /rts/Messages.c
parent069cd16951bd45a55c94b5adce048c4ec9aad2c8 (diff)
downloadhaskell-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.c43
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
+}
+
+