Ian, Simon,

The following patch is attached.

        Add eventlog event for thread labels
        
        The existing GHC.Conc.labelThread will now also emit the the
        thread
        label into the eventlog. Profiling tools like ThreadScope could
        then
        use the thread labels rather than thread numbers.

It should help us a bit with things like IO manager profiling.

I've validated it, but I've not pushed since I'm aware that we're in the
process of making the 7.4 branch. Ideally I'd like to include it in
7.4.x but it's not critical (I expect this to be my last eventlog patch
targeting the 7.4 branch).

-- 
Duncan Coutts, Haskell Consultant
Well-Typed LLP, http://www.well-typed.com/
>From b84c9fd7bc6402ca296f0970644383d05132dac1 Mon Sep 17 00:00:00 2001
From: Duncan Coutts <[email protected]>
Date: Wed, 2 Nov 2011 12:02:09 +0000
Subject: [PATCH] Add eventlog event for thread labels

The existing GHC.Conc.labelThread will now also emit the the thread
label into the eventlog. Profiling tools like ThreadScope could then
use the thread labels rather than thread numbers.
---
 includes/rts/EventLogFormat.h |    6 +++---
 rts/PrimOps.cmm               |    4 ++--
 rts/RtsProbes.d               |    1 +
 rts/ThreadLabels.c            |   15 +++++++++++----
 rts/ThreadLabels.h            |    4 +++-
 rts/Trace.c                   |   18 ++++++++++++++++++
 rts/Trace.h                   |   23 +++++++++++++++++++++++
 rts/eventlog/EventLog.c       |   27 +++++++++++++++++++++++++++
 rts/eventlog/EventLog.h       |   13 +++++++++++++
 9 files changed, 101 insertions(+), 10 deletions(-)

diff --git a/includes/rts/EventLogFormat.h b/includes/rts/EventLogFormat.h
index 7773bae..0b276b1 100644
--- a/includes/rts/EventLogFormat.h
+++ b/includes/rts/EventLogFormat.h
@@ -142,9 +142,9 @@
 #define EVENT_SPARK_GC            41 /* ()                     */
 #define EVENT_INTERN_STRING       42 /* (string, id) {not used by ghc} */
 #define EVENT_WALL_CLOCK_TIME     43 /* (capset, unix_epoch_seconds, nanoseconds) */
+#define EVENT_THREAD_LABEL        44 /* (thread, name_string)  */
 
-
-/* Range 44 - 59 is available for new GHC and common events */
+/* Range 45 - 59 is available for new GHC and common events */
 
 /* Range 60 - 80 is used by eden for parallel tracing
  * see http://www.mathematik.uni-marburg.de/~eden/
@@ -157,7 +157,7 @@
  * ranges higher than this are reserved but not currently emitted by ghc.
  * This must match the size of the EventDesc[] array in EventLog.c
  */
-#define NUM_GHC_EVENT_TAGS        44
+#define NUM_GHC_EVENT_TAGS        45
 
 #if 0  /* DEPRECATED EVENTS: */
 /* we don't actually need to record the thread, it's implicit */
diff --git a/rts/PrimOps.cmm b/rts/PrimOps.cmm
index bb4f73b..ed310a6 100644
--- a/rts/PrimOps.cmm
+++ b/rts/PrimOps.cmm
@@ -631,8 +631,8 @@ stg_labelThreadzh
   /* args: 
 	R1 = ThreadId#
 	R2 = Addr# */
-#ifdef DEBUG
-  foreign "C" labelThread(R1 "ptr", R2 "ptr") [];
+#if defined(DEBUG) || defined(TRACING) || defined(DTRACE)
+  foreign "C" labelThread(MyCapability() "ptr", R1 "ptr", R2 "ptr") [];
 #endif
   jump %ENTRY_CODE(Sp(0));
 }
diff --git a/rts/RtsProbes.d b/rts/RtsProbes.d
index 0400510..1c74619 100644
--- a/rts/RtsProbes.d
+++ b/rts/RtsProbes.d
@@ -50,6 +50,7 @@ provider HaskellEvent {
   probe request__seq__gc (EventCapNo);
   probe request__par__gc (EventCapNo);
   probe create__spark__thread (EventCapNo, EventThreadID);
+  probe thread__label (EventCapNo, EventThreadID, char *);
 
   /* other events */
 /* This one doesn't seem to be used at all at the moment: */
diff --git a/rts/ThreadLabels.c b/rts/ThreadLabels.c
index 6d2a5d6..8838042 100644
--- a/rts/ThreadLabels.c
+++ b/rts/ThreadLabels.c
@@ -13,12 +13,13 @@
 #include "ThreadLabels.h"
 #include "RtsUtils.h"
 #include "Hash.h"
+#include "Trace.h"
 
 #include <stdlib.h>
 #include <string.h>
 
 #if defined(DEBUG)
-/* to the end */
+
 static HashTable * threadLabels = NULL;
 
 void
@@ -61,9 +62,14 @@ removeThreadLabel(StgWord key)
   }  
 }
 
+#endif /* DEBUG */
+
 void
-labelThread(StgPtr tso, char *label)
+labelThread(Capability *cap   STG_UNUSED,
+            StgTSO     *tso   STG_UNUSED,
+            char       *label STG_UNUSED)
 {
+#if defined(DEBUG)
   int len;
   void *buf;
 
@@ -72,7 +78,8 @@ labelThread(StgPtr tso, char *label)
   buf = stgMallocBytes(len * sizeof(char), "Schedule.c:labelThread()");
   strncpy(buf,label,len);
   /* Update will free the old memory for us */
-  updateThreadLabel(((StgTSO *)tso)->id,buf);
+  updateThreadLabel(tso->id,buf);
+#endif
+  traceThreadLabel(cap, tso, label);
 }
 
-#endif /* DEBUG */
diff --git a/rts/ThreadLabels.h b/rts/ThreadLabels.h
index 254b91e..742e77a 100644
--- a/rts/ThreadLabels.h
+++ b/rts/ThreadLabels.h
@@ -17,8 +17,10 @@ void    initThreadLabelTable (void);
 void    freeThreadLabelTable (void);
 void *  lookupThreadLabel    (StgWord key);
 void    removeThreadLabel    (StgWord key);
-void    labelThread          (StgPtr tso, char *label);
 #endif
+void    labelThread          (Capability *cap,
+                              StgTSO     *tso,
+                              char       *label);
 
 #include "EndPrivate.h"
 
diff --git a/rts/Trace.c b/rts/Trace.c
index a3aa266..1671bfe 100644
--- a/rts/Trace.c
+++ b/rts/Trace.c
@@ -547,6 +547,24 @@ void traceUserMsg(Capability *cap, char *msg)
     traceFormatUserMsg(cap, "%s", msg);
 }
 
+void traceThreadLabel_(Capability *cap,
+                       StgTSO     *tso,
+                       char       *label)
+{
+#ifdef DEBUG
+    if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
+        ACQUIRE_LOCK(&trace_utx);
+        tracePreface();
+        debugBelch("cap %d: thread %lu has label %s\n",
+                   cap->no, (lnat)tso->id, label);
+        RELEASE_LOCK(&trace_utx);
+    } else
+#endif
+    {
+        postThreadLabel(cap, tso->id, label);
+    }
+}
+
 void traceThreadStatus_ (StgTSO *tso USED_IF_DEBUG)
 {
 #ifdef DEBUG
diff --git a/rts/Trace.h b/rts/Trace.h
index a0c5e26..8dacb80 100644
--- a/rts/Trace.h
+++ b/rts/Trace.h
@@ -152,9 +152,18 @@ void trace_(char *msg, ...);
 
 /* 
  * A message or event emitted by the program
+ * Used by Debug.Trace.{traceEvent, traceEventIO}
  */
 void traceUserMsg(Capability *cap, char *msg);
 
+/*
+ * An event to record a Haskell thread's label/name
+ * Used by GHC.Conc.labelThread
+ */
+void traceThreadLabel_(Capability *cap,
+                       StgTSO     *tso,
+                       char       *label);
+
 /* 
  * Emit a debug message (only when DEBUG is defined)
  */
@@ -221,6 +230,7 @@ void traceSparkCounters_ (Capability *cap,
 #define debugTrace(class, str, ...) /* nothing */
 #define debugTraceCap(class, cap, str, ...) /* nothing */
 #define traceThreadStatus(class, tso) /* nothing */
+#define traceThreadLabel_(cap, tso, label) /* nothing */
 INLINE_HEADER void traceEventStartup_ (int n_caps STG_UNUSED) {};
 #define traceCapsetEvent_(tag, capset, info) /* nothing */
 #define traceWallClockTime_() /* nothing */
@@ -268,6 +278,8 @@ void dtraceUserMsgWrapper(Capability *cap, char *msg);
     HASKELLEVENT_REQUEST_PAR_GC(cap)
 #define dtraceCreateSparkThread(cap, spark_tid)         \
     HASKELLEVENT_CREATE_SPARK_THREAD(cap, spark_tid)
+#define dtraceThreadLabel(cap, tso, label)              \
+    HASKELLEVENT_THREAD_LABEL(cap, tso, label)
 INLINE_HEADER void dtraceStartup (int num_caps) {
     HASKELLEVENT_STARTUP(num_caps);
 }
@@ -318,6 +330,7 @@ INLINE_HEADER void dtraceStartup (int num_caps) {
 #define dtraceRequestSeqGc(cap)                         /* nothing */
 #define dtraceRequestParGc(cap)                         /* nothing */
 #define dtraceCreateSparkThread(cap, spark_tid)         /* nothing */
+#define dtraceThreadLabel(cap, tso, label)              /* nothing */
 INLINE_HEADER void dtraceStartup (int num_caps STG_UNUSED) {};
 #define dtraceUserMsg(cap, msg)                         /* nothing */
 #define dtraceGcIdle(cap)                               /* nothing */
@@ -414,6 +427,16 @@ INLINE_HEADER void traceEventThreadWakeup(Capability *cap       STG_UNUSED,
                        (EventCapNo)other_cap);
 }
 
+INLINE_HEADER void traceThreadLabel(Capability *cap   STG_UNUSED,
+                                    StgTSO     *tso   STG_UNUSED,
+                                    char       *label STG_UNUSED)
+{
+    if (RTS_UNLIKELY(TRACE_sched)) {
+        traceThreadLabel_(cap, tso, label);
+    }
+    dtraceThreadLabel((EventCapNo)cap->no, (EventThreadID)tso->id, label);
+}
+
 INLINE_HEADER void traceEventGcStart(Capability *cap STG_UNUSED)
 {
     traceGcEvent(cap, EVENT_GC_START);
diff --git a/rts/eventlog/EventLog.c b/rts/eventlog/EventLog.c
index 09e12a2..9547e7c 100644
--- a/rts/eventlog/EventLog.c
+++ b/rts/eventlog/EventLog.c
@@ -62,6 +62,7 @@ char *EventDesc[] = {
   [EVENT_MIGRATE_THREAD]      = "Migrate thread",
   [EVENT_SHUTDOWN]            = "Shutdown",
   [EVENT_THREAD_WAKEUP]       = "Wakeup thread",
+  [EVENT_THREAD_LABEL]        = "Thread label",
   [EVENT_GC_START]            = "Starting GC",
   [EVENT_GC_END]              = "Finished GC",
   [EVENT_REQUEST_SEQ_GC]      = "Request sequential GC",
@@ -332,6 +333,7 @@ initEventLogging(void)
         case EVENT_RTS_IDENTIFIER:   // (capset, str)
         case EVENT_PROGRAM_ARGS:     // (capset, strvec)
         case EVENT_PROGRAM_ENV:      // (capset, strvec)
+        case EVENT_THREAD_LABEL:     // (thread, str)
             eventTypes[t].size = 0xffff;
             break;
 
@@ -791,6 +793,31 @@ void postEventStartup(EventCapNo n_caps)
     RELEASE_LOCK(&eventBufMutex);
 }
 
+void postThreadLabel(Capability    *cap,
+                     EventThreadID  id,
+                     char          *label)
+{
+    EventsBuf *eb;
+    int strsize = strlen(label);
+    int size = strsize + sizeof(EventCapsetID);
+
+    eb = &capEventBuf[cap->no];
+
+    if (!hasRoomForVariableEvent(eb, size)){
+        printAndClearEventBuf(eb);
+
+        if (!hasRoomForVariableEvent(eb, size)){
+            // Event size exceeds buffer size, bail out:
+            return;
+        }
+    }
+
+    postEventHeader(eb, EVENT_THREAD_LABEL);
+    postPayloadSize(eb, size);
+    postThreadID(eb, id);
+    postBuf(eb, (StgWord8*) label, strsize);
+}
+
 void closeBlockMarker (EventsBuf *ebuf)
 {
     StgInt8* save_pos;
diff --git a/rts/eventlog/EventLog.h b/rts/eventlog/EventLog.h
index d7368c3..667f348 100644
--- a/rts/eventlog/EventLog.h
+++ b/rts/eventlog/EventLog.h
@@ -83,6 +83,13 @@ void postSparkCountersEvent (Capability *cap,
                              SparkCounters counters,
                              StgWord remaining);
 
+/*
+ * Post an event to annotate a thread with a label
+ */
+void postThreadLabel(Capability    *cap,
+                     EventThreadID  id,
+                     char          *label);
+
 #else /* !TRACING */
 
 INLINE_HEADER void postSchedEvent (Capability *cap  STG_UNUSED,
@@ -105,6 +112,12 @@ INLINE_HEADER void postCapMsg (Capability *cap STG_UNUSED,
                                va_list ap STG_UNUSED)
 { /* nothing */ }
 
+
+INLINE_HEADER void postThreadLabel(Capability    *cap   STG_UNUSED,
+                                   EventThreadID  id    STG_UNUSED,
+                                   char          *label STG_UNUSED)
+{ /* nothing */ }
+                                   
 #endif
 
 #include "EndPrivate.h"
-- 
1.7.3.4

_______________________________________________
Cvs-ghc mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/cvs-ghc

Reply via email to