[Git][ghc/ghc][wip/wenkokke/trace-ipe] 2 commits: rts: Add IPE tracing flag
Wen Kokke pushed to branch wip/wenkokke/trace-ipe at Glasgow Haskell Compiler / GHC Commits: 6ea93eaf by Wen Kokke at 2026-05-07T17:57:20+01:00 rts: Add IPE tracing flag - - - - - bda2c065 by Wen Kokke at 2026-05-07T17:57:22+01:00 rts: Skip IPE tracing if TRACE_ipe is false. - - - - - 6 changed files: - rts/IPE.c - rts/RtsFlags.c - rts/Trace.c - rts/Trace.h - rts/include/rts/EventLogWriter.h - rts/include/rts/Flags.h Changes: ===================================== rts/IPE.c ===================================== @@ -165,26 +165,46 @@ static void traceIPEFromHashTable(void *data STG_UNUSED, StgWord key STG_UNUSED, } void dumpIPEToEventLog(void) { - // Dump pending entries - IpeBufferListNode *node = RELAXED_LOAD(&ipeBufferList); - while (node != NULL) { - if (ipe_node_valid(node)){ - decompressIPEBufferListNodeIfCompressed(node); - - for (uint32_t i = 0; i < node->count; i++) { - const InfoProvEnt ent = ipeBufferEntryToIpe(node, i); - traceIPE(&ent); - } + /* + Usually, traceX functions are defined as a pair of a traceX_ function that + traces unconditionally and a traceX functional macro that performs the test + for the relevant TRACE_x flag. + + This function is the only function that calls traceIPE, but it takes a lot + of work just to prepare the IPE information. If traceIPE does not trace that + IPE information, all that work is wasted. Hence, the test of TRACE_ipe is + performed in this function instead. + + This function is called via traceInitEvent in RtsStartup.c, which registers + it as an init event handler. It is important that this happens regardless + of whether or not IPE tracing is enabled at startup, since IPE tracing can + be started/stopped at runtime using the dynamic trace flags API. + + IPE tracing is enabled whenever IPE debug printing is enabled via -DI, so + this test does not prevent IPE debug printing. + */ + if (RTS_UNLIKELY(TRACE_ipe)) { + // Dump pending entries + IpeBufferListNode *node = RELAXED_LOAD(&ipeBufferList); + while (node != NULL) { + if (ipe_node_valid(node)){ + decompressIPEBufferListNodeIfCompressed(node); + + for (uint32_t i = 0; i < node->count; i++) { + const InfoProvEnt ent = ipeBufferEntryToIpe(node, i); + traceIPE(&ent); + } + } + node = node->next; } - node = node->next; - } - // Dump entries already in hashmap - ACQUIRE_LOCK(&ipeMapLock); - if (ipeMap != NULL) { - mapHashTable(ipeMap, NULL, &traceIPEFromHashTable); + // Dump entries already in hashmap + ACQUIRE_LOCK(&ipeMapLock); + if (ipeMap != NULL) { + mapHashTable(ipeMap, NULL, &traceIPEFromHashTable); + } + RELEASE_LOCK(&ipeMapLock); } - RELEASE_LOCK(&ipeMapLock); } ===================================== rts/RtsFlags.c ===================================== @@ -249,6 +249,7 @@ void initRtsFlagsDefaults(void) RtsFlags.TraceFlags.sparks_sampled= false; RtsFlags.TraceFlags.sparks_full = false; RtsFlags.TraceFlags.user = false; + RtsFlags.TraceFlags.ipe = false; RtsFlags.TraceFlags.ticky = false; RtsFlags.TraceFlags.trace_output = NULL; # if defined(THREADED_RTS) @@ -449,6 +450,7 @@ usage_text[] = { " p par spark events (sampled)", " f par spark events (full detail)", " u user events (emitted from Haskell code)", +" I IPE events", #if defined(TICKY_TICKY) " T ticky-ticky counter samples", #endif @@ -2528,6 +2530,7 @@ static void read_trace_flags(const char *arg) RtsFlags.TraceFlags.gc = true; RtsFlags.TraceFlags.sparks_sampled = true; RtsFlags.TraceFlags.user = true; + RtsFlags.TraceFlags.ipe = true; for (c = arg; *c != '\0'; c++) { switch(*c) { @@ -2541,8 +2544,9 @@ static void read_trace_flags(const char *arg) RtsFlags.TraceFlags.gc = enabled; RtsFlags.TraceFlags.sparks_sampled = enabled; RtsFlags.TraceFlags.sparks_full = enabled; - RtsFlags.TraceFlags.user = enabled; RtsFlags.TraceFlags.nonmoving_gc = enabled; + RtsFlags.TraceFlags.user = enabled; + RtsFlags.TraceFlags.ipe = enabled; #if defined(TICKY_TICKY) RtsFlags.TraceFlags.ticky = enabled; #endif @@ -2577,6 +2581,10 @@ static void read_trace_flags(const char *arg) RtsFlags.TraceFlags.user = enabled; enabled = true; break; + case 'I': + RtsFlags.TraceFlags.ipe = enabled; + enabled = true; + break; case 'T': #if defined(TICKY_TICKY) RtsFlags.TraceFlags.ticky = enabled; ===================================== rts/Trace.c ===================================== @@ -47,6 +47,8 @@ bool getTraceFlag(RUNTIME_TRACE_FLAG flag) { return RuntimeTraceFlagCache.user; case TRACE_CAP: return RuntimeTraceFlagCache.cap; + case TRACE_IPE: + return RuntimeTraceFlagCache.ipe; default: return false; } @@ -75,6 +77,9 @@ void setTraceFlag(RUNTIME_TRACE_FLAG flag, bool value) { case TRACE_CAP: RuntimeTraceFlagCache.cap = value; break; + case TRACE_IPE: + RuntimeTraceFlagCache.ipe = value; + break; } } @@ -119,13 +124,19 @@ static void updateTraceFlagCache(void) { RuntimeTraceFlagCache.user = RtsFlags.TraceFlags.user; + // -DI turns on IPE tracing too + RuntimeTraceFlagCache.ipe = + RtsFlags.TraceFlags.ipe || + RtsFlags.DebugFlags.ipe; + // We trace cap events if we're tracing anything else RuntimeTraceFlagCache.cap = TRACE_sched || TRACE_gc || TRACE_spark_sampled || TRACE_spark_full || - TRACE_user; + TRACE_user || + TRACE_ipe; } void initTracing (void) @@ -720,6 +731,7 @@ void traceHeapProfSampleString(const char *label, StgWord residency) } } +// The TRACE_ipe test happens in dumpIPEToEventLog. void traceIPE(const InfoProvEnt *ipe) { #if defined(DEBUG) ===================================== rts/Trace.h ===================================== @@ -79,6 +79,7 @@ enum CapsetType { CapsetTypeCustom = CAPSET_TYPE_CUSTOM, #define TRACE_spark_full ((const bool)RuntimeTraceFlagCache.spark_full) #define TRACE_user ((const bool)RuntimeTraceFlagCache.user) #define TRACE_cap ((const bool)RuntimeTraceFlagCache.cap) +#define TRACE_ipe ((const bool)RuntimeTraceFlagCache.ipe) /* * Runtime trace flags. @@ -91,6 +92,7 @@ typedef struct { bool spark_full; bool user; bool cap; + bool ipe; } RUNTIME_TRACE_FLAG_CACHE; /* ===================================== rts/include/rts/EventLogWriter.h ===================================== @@ -90,6 +90,7 @@ typedef enum { TRACE_SPARK_FULL, TRACE_USER, TRACE_CAP, + TRACE_IPE, } RUNTIME_TRACE_FLAG; /* ===================================== rts/include/rts/Flags.h ===================================== @@ -191,6 +191,7 @@ typedef struct _TRACE_FLAGS { bool sparks_full; /* trace spark events 100% accurately */ bool ticky; /* trace ticky-ticky samples */ bool user; /* trace user events (emitted from Haskell code) */ + bool ipe; /* trace IPE events */ #if defined(THREADED_RTS) /* Time between force eventlog flushes (or 0 if disabled) */ Time eventlogFlushTime; View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/4af2394e1d25c53b28bcf657f5d4844... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/4af2394e1d25c53b28bcf657f5d4844... You're receiving this email because of your account on gitlab.haskell.org.
participants (1)
-
Wen Kokke (@wenkokke)