Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
-
1cb1d672
by Wen Kokke at 2026-05-06T09:53:40-04:00
-
9d54dc94
by Wen Kokke at 2026-05-06T09:53:40-04:00
-
418d737b
by Wen Kokke at 2026-05-06T09:53:40-04:00
-
99f4afa4
by Wen Kokke at 2026-05-06T09:53:40-04:00
-
7e9eb8b9
by Wen Kokke at 2026-05-06T09:53:40-04:00
-
3a3045fb
by Wen Kokke at 2026-05-06T09:53:41-04:00
6 changed files:
- + changelog.d/dynamic-trace-flags
- rts/RtsSymbols.c
- rts/Trace.c
- rts/Trace.h
- rts/include/rts/EventLogWriter.h
- rts/sm/NonMoving.c
Changes:
| 1 | +section: compiler
|
|
| 2 | +synopsis: Support dynamic trace flags in RTS
|
|
| 3 | +issues: #27186
|
|
| 4 | +mrs: !15936
|
|
| 5 | + |
|
| 6 | +description: {
|
|
| 7 | + The RTS API now exposes the `RUNTIME_TRACE_FLAG` type and
|
|
| 8 | + the `getTraceFlags` and `setTraceFlags` functions that can be used to
|
|
| 9 | + change the trace flags at runtime.
|
|
| 10 | +} |
| ... | ... | @@ -540,7 +540,12 @@ extern char **environ; |
| 540 | 540 | SymI_HasProto(__word_encodeFloat) \
|
| 541 | 541 | SymI_HasDataProto(stg_atomicallyzh) \
|
| 542 | 542 | SymI_HasProto(barf) \
|
| 543 | + SymI_HasProto(startEventLogging) \
|
|
| 544 | + SymI_HasProto(endEventLogging) \
|
|
| 543 | 545 | SymI_HasProto(flushEventLog) \
|
| 546 | + SymI_HasProto(flushEventLog) \
|
|
| 547 | + SymI_HasProto(getTraceFlag) \
|
|
| 548 | + SymI_HasProto(setTraceFlag) \
|
|
| 544 | 549 | SymI_HasProto(deRefStablePtr) \
|
| 545 | 550 | SymI_HasProto(debugBelch) \
|
| 546 | 551 | SymI_HasProto(errorBelch) \
|
| ... | ... | @@ -29,14 +29,54 @@ |
| 29 | 29 | #include <unistd.h>
|
| 30 | 30 | #endif
|
| 31 | 31 | |
| 32 | -// events
|
|
| 33 | -uint8_t TRACE_sched;
|
|
| 34 | -uint8_t TRACE_gc;
|
|
| 35 | -uint8_t TRACE_nonmoving_gc;
|
|
| 36 | -uint8_t TRACE_spark_sampled;
|
|
| 37 | -uint8_t TRACE_spark_full;
|
|
| 38 | -uint8_t TRACE_user;
|
|
| 39 | -uint8_t TRACE_cap;
|
|
| 32 | +RUNTIME_TRACE_FLAG_CACHE RuntimeTraceFlagCache = {0};
|
|
| 33 | + |
|
| 34 | +bool getTraceFlag(RUNTIME_TRACE_FLAG flag) {
|
|
| 35 | + switch (flag) {
|
|
| 36 | + case TRACE_SCHEDULER:
|
|
| 37 | + return RuntimeTraceFlagCache.scheduler;
|
|
| 38 | + case TRACE_GC:
|
|
| 39 | + return RuntimeTraceFlagCache.gc;
|
|
| 40 | + case TRACE_NONMOVING_GC:
|
|
| 41 | + return RuntimeTraceFlagCache.nonmoving_gc;
|
|
| 42 | + case TRACE_SPARK_SAMPLED:
|
|
| 43 | + return RuntimeTraceFlagCache.spark_sampled;
|
|
| 44 | + case TRACE_SPARK_FULL:
|
|
| 45 | + return RuntimeTraceFlagCache.spark_full;
|
|
| 46 | + case TRACE_USER:
|
|
| 47 | + return RuntimeTraceFlagCache.user;
|
|
| 48 | + case TRACE_CAP:
|
|
| 49 | + return RuntimeTraceFlagCache.cap;
|
|
| 50 | + default:
|
|
| 51 | + return false;
|
|
| 52 | + }
|
|
| 53 | +}
|
|
| 54 | + |
|
| 55 | +void setTraceFlag(RUNTIME_TRACE_FLAG flag, bool value) {
|
|
| 56 | + switch (flag) {
|
|
| 57 | + case TRACE_SCHEDULER:
|
|
| 58 | + RuntimeTraceFlagCache.scheduler = value;
|
|
| 59 | + break;
|
|
| 60 | + case TRACE_GC:
|
|
| 61 | + RuntimeTraceFlagCache.gc = value;
|
|
| 62 | + break;
|
|
| 63 | + case TRACE_NONMOVING_GC:
|
|
| 64 | + RuntimeTraceFlagCache.nonmoving_gc = value;
|
|
| 65 | + break;
|
|
| 66 | + case TRACE_SPARK_SAMPLED:
|
|
| 67 | + RuntimeTraceFlagCache.spark_sampled = value;
|
|
| 68 | + break;
|
|
| 69 | + case TRACE_SPARK_FULL:
|
|
| 70 | + RuntimeTraceFlagCache.spark_full = value;
|
|
| 71 | + break;
|
|
| 72 | + case TRACE_USER:
|
|
| 73 | + RuntimeTraceFlagCache.user = value;
|
|
| 74 | + break;
|
|
| 75 | + case TRACE_CAP:
|
|
| 76 | + RuntimeTraceFlagCache.cap = value;
|
|
| 77 | + break;
|
|
| 78 | + }
|
|
| 79 | +}
|
|
| 40 | 80 | |
| 41 | 81 | #if defined(THREADED_RTS)
|
| 42 | 82 | static Mutex trace_utx;
|
| ... | ... | @@ -51,43 +91,41 @@ static void traceCap_stderr(Capability *cap, char *msg, ...); |
| 51 | 91 | --------------------------------------------------------------------------- */
|
| 52 | 92 | |
| 53 | 93 | /*
|
| 54 | - * Update the TRACE_* globals. Must be called whenever RtsFlags.TraceFlags is
|
|
| 55 | - * modified.
|
|
| 94 | + * Initialise the runtime trace flags from RtsFlags.TraceFlags.
|
|
| 56 | 95 | */
|
| 57 | -static void updateTraceFlagCache (void)
|
|
| 58 | -{
|
|
| 59 | - // -Ds turns on scheduler tracing too
|
|
| 60 | - TRACE_sched =
|
|
| 61 | - RtsFlags.TraceFlags.scheduler ||
|
|
| 62 | - RtsFlags.DebugFlags.scheduler;
|
|
| 63 | - |
|
| 64 | - // -Dg turns on gc tracing too
|
|
| 65 | - TRACE_gc =
|
|
| 66 | - RtsFlags.TraceFlags.gc ||
|
|
| 67 | - RtsFlags.DebugFlags.gc ||
|
|
| 68 | - RtsFlags.DebugFlags.scheduler;
|
|
| 69 | - |
|
| 70 | - TRACE_nonmoving_gc =
|
|
| 71 | - RtsFlags.TraceFlags.nonmoving_gc;
|
|
| 72 | - |
|
| 73 | - TRACE_spark_sampled =
|
|
| 74 | - RtsFlags.TraceFlags.sparks_sampled;
|
|
| 75 | - |
|
| 76 | - // -Dr turns on full spark tracing
|
|
| 77 | - TRACE_spark_full =
|
|
| 78 | - RtsFlags.TraceFlags.sparks_full ||
|
|
| 79 | - RtsFlags.DebugFlags.sparks;
|
|
| 80 | - |
|
| 81 | - TRACE_user =
|
|
| 82 | - RtsFlags.TraceFlags.user;
|
|
| 83 | - |
|
| 84 | - // We trace cap events if we're tracing anything else
|
|
| 85 | - TRACE_cap =
|
|
| 86 | - TRACE_sched ||
|
|
| 87 | - TRACE_gc ||
|
|
| 88 | - TRACE_spark_sampled ||
|
|
| 89 | - TRACE_spark_full ||
|
|
| 90 | - TRACE_user;
|
|
| 96 | +static void updateTraceFlagCache(void) {
|
|
| 97 | + // -Ds turns on scheduler tracing too
|
|
| 98 | + RuntimeTraceFlagCache.scheduler =
|
|
| 99 | + RtsFlags.TraceFlags.scheduler ||
|
|
| 100 | + RtsFlags.DebugFlags.scheduler;
|
|
| 101 | + |
|
| 102 | + // -Dg turns on gc tracing too
|
|
| 103 | + RuntimeTraceFlagCache.gc =
|
|
| 104 | + RtsFlags.TraceFlags.gc ||
|
|
| 105 | + RtsFlags.DebugFlags.gc ||
|
|
| 106 | + RtsFlags.DebugFlags.scheduler;
|
|
| 107 | + |
|
| 108 | + RuntimeTraceFlagCache.nonmoving_gc =
|
|
| 109 | + RtsFlags.TraceFlags.nonmoving_gc;
|
|
| 110 | + |
|
| 111 | + RuntimeTraceFlagCache.spark_sampled =
|
|
| 112 | + RtsFlags.TraceFlags.sparks_sampled;
|
|
| 113 | + |
|
| 114 | + // -Dr turns on full spark tracing
|
|
| 115 | + RuntimeTraceFlagCache.spark_full =
|
|
| 116 | + RtsFlags.TraceFlags.sparks_full ||
|
|
| 117 | + RtsFlags.DebugFlags.sparks;
|
|
| 118 | + |
|
| 119 | + RuntimeTraceFlagCache.user =
|
|
| 120 | + RtsFlags.TraceFlags.user;
|
|
| 121 | + |
|
| 122 | + // We trace cap events if we're tracing anything else
|
|
| 123 | + RuntimeTraceFlagCache.cap =
|
|
| 124 | + TRACE_sched ||
|
|
| 125 | + TRACE_gc ||
|
|
| 126 | + TRACE_spark_sampled ||
|
|
| 127 | + TRACE_spark_full ||
|
|
| 128 | + TRACE_user;
|
|
| 91 | 129 | }
|
| 92 | 130 | |
| 93 | 131 | void initTracing (void)
|
| ... | ... | @@ -880,59 +918,65 @@ void traceThreadLabel_(Capability *cap, |
| 880 | 918 | }
|
| 881 | 919 | }
|
| 882 | 920 | |
| 883 | -void traceConcMarkBegin(void)
|
|
| 921 | +void traceNonmovingGcEvent_ (EventTypeNum tag)
|
|
| 884 | 922 | {
|
| 885 | - if (eventlog_enabled)
|
|
| 886 | - postEventNoCap(EVENT_CONC_MARK_BEGIN);
|
|
| 923 | +#if defined(DEBUG)
|
|
| 924 | + if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
|
|
| 925 | + /* nothing - no string representation for nonmoving GC events */
|
|
| 926 | + } else
|
|
| 927 | +#endif
|
|
| 928 | + {
|
|
| 929 | + /* currently most non-moving GC events are nullary events */
|
|
| 930 | + postEventNoCap(tag);
|
|
| 931 | + }
|
|
| 887 | 932 | }
|
| 888 | 933 | |
| 889 | -void traceConcMarkEnd(StgWord32 marked_obj_count)
|
|
| 934 | +void traceConcMarkEnd_(StgWord32 marked_obj_count)
|
|
| 890 | 935 | {
|
| 891 | - if (eventlog_enabled)
|
|
| 936 | +#if defined(DEBUG)
|
|
| 937 | + if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
|
|
| 938 | + /* nothing - no string representation for nonmoving GC events */
|
|
| 939 | + } else
|
|
| 940 | +#endif
|
|
| 941 | + {
|
|
| 892 | 942 | postConcMarkEnd(marked_obj_count);
|
| 943 | + }
|
|
| 893 | 944 | }
|
| 894 | 945 | |
| 895 | -void traceConcSyncBegin(void)
|
|
| 896 | -{
|
|
| 897 | - if (eventlog_enabled)
|
|
| 898 | - postEventNoCap(EVENT_CONC_SYNC_BEGIN);
|
|
| 899 | -}
|
|
| 900 | - |
|
| 901 | -void traceConcSyncEnd(void)
|
|
| 902 | -{
|
|
| 903 | - if (eventlog_enabled)
|
|
| 904 | - postEventNoCap(EVENT_CONC_SYNC_END);
|
|
| 905 | -}
|
|
| 906 | - |
|
| 907 | -void traceConcSweepBegin(void)
|
|
| 908 | -{
|
|
| 909 | - if (eventlog_enabled)
|
|
| 910 | - postEventNoCap(EVENT_CONC_SWEEP_BEGIN);
|
|
| 911 | -}
|
|
| 912 | - |
|
| 913 | -void traceConcSweepEnd(void)
|
|
| 914 | -{
|
|
| 915 | - if (eventlog_enabled)
|
|
| 916 | - postEventNoCap(EVENT_CONC_SWEEP_END);
|
|
| 917 | -}
|
|
| 918 | - |
|
| 919 | -void traceConcUpdRemSetFlush(Capability *cap)
|
|
| 946 | +void traceConcUpdRemSetFlush_(Capability *cap)
|
|
| 920 | 947 | {
|
| 921 | - if (eventlog_enabled)
|
|
| 948 | +#if defined(DEBUG)
|
|
| 949 | + if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
|
|
| 950 | + /* nothing - no string representation for nonmoving GC events */
|
|
| 951 | + } else
|
|
| 952 | +#endif
|
|
| 953 | + {
|
|
| 922 | 954 | postConcUpdRemSetFlush(cap);
|
| 955 | + }
|
|
| 923 | 956 | }
|
| 924 | 957 | |
| 925 | -void traceNonmovingHeapCensus(uint16_t blk_size,
|
|
| 926 | - const struct NonmovingAllocCensus *census)
|
|
| 958 | +void traceNonmovingHeapCensus_(uint16_t blk_size, const struct NonmovingAllocCensus *census)
|
|
| 927 | 959 | {
|
| 928 | - if (eventlog_enabled && TRACE_nonmoving_gc)
|
|
| 960 | +#if defined(DEBUG)
|
|
| 961 | + if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
|
|
| 962 | + /* nothing - no string representation for nonmoving GC events */
|
|
| 963 | + } else
|
|
| 964 | +#endif
|
|
| 965 | + {
|
|
| 929 | 966 | postNonmovingHeapCensus(blk_size, census);
|
| 967 | + }
|
|
| 930 | 968 | }
|
| 931 | 969 | |
| 932 | -void traceNonmovingPrunedSegments(uint32_t pruned_segments, uint32_t free_segments)
|
|
| 970 | +void traceNonmovingPrunedSegments_(uint32_t pruned_segments, uint32_t free_segments)
|
|
| 933 | 971 | {
|
| 934 | - if (eventlog_enabled && TRACE_nonmoving_gc)
|
|
| 972 | +#if defined(DEBUG)
|
|
| 973 | + if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
|
|
| 974 | + /* nothing - no string representation for nonmoving GC events */
|
|
| 975 | + } else
|
|
| 976 | +#endif
|
|
| 977 | + {
|
|
| 935 | 978 | postNonmovingPrunedSegments(pruned_segments, free_segments);
|
| 979 | + }
|
|
| 936 | 980 | }
|
| 937 | 981 | |
| 938 | 982 | void traceThreadStatus_ (StgTSO *tso USED_IF_DEBUG)
|
| ... | ... | @@ -70,16 +70,35 @@ enum CapsetType { CapsetTypeCustom = CAPSET_TYPE_CUSTOM, |
| 70 | 70 | #define DEBUG_continuation RtsFlags.DebugFlags.continuation
|
| 71 | 71 | #define DEBUG_iomanager RtsFlags.DebugFlags.iomanager
|
| 72 | 72 | |
| 73 | -// Event-enabled flags
|
|
| 74 | -// These semantically booleans but we use a dense packing to minimize their
|
|
| 75 | -// cache impact.
|
|
| 76 | -extern uint8_t TRACE_sched;
|
|
| 77 | -extern uint8_t TRACE_gc;
|
|
| 78 | -extern uint8_t TRACE_nonmoving_gc;
|
|
| 79 | -extern uint8_t TRACE_spark_sampled;
|
|
| 80 | -extern uint8_t TRACE_spark_full;
|
|
| 81 | -extern uint8_t TRACE_cap;
|
|
| 82 | -/* extern uint8_t TRACE_user; */ // only used in Trace.c
|
|
| 73 | +// These trace flags are shorthand for the members of the RuntimeTraceFlagCache
|
|
| 74 | +// struct. Within the RTS, these should be treated as read-only variables.
|
|
| 75 | +#define TRACE_sched ((const bool)RuntimeTraceFlagCache.scheduler)
|
|
| 76 | +#define TRACE_gc ((const bool)RuntimeTraceFlagCache.gc)
|
|
| 77 | +#define TRACE_nonmoving_gc ((const bool)RuntimeTraceFlagCache.nonmoving_gc)
|
|
| 78 | +#define TRACE_spark_sampled ((const bool)RuntimeTraceFlagCache.spark_sampled)
|
|
| 79 | +#define TRACE_spark_full ((const bool)RuntimeTraceFlagCache.spark_full)
|
|
| 80 | +#define TRACE_user ((const bool)RuntimeTraceFlagCache.user)
|
|
| 81 | +#define TRACE_cap ((const bool)RuntimeTraceFlagCache.cap)
|
|
| 82 | + |
|
| 83 | +/*
|
|
| 84 | + * Runtime trace flags.
|
|
| 85 | + */
|
|
| 86 | +typedef struct {
|
|
| 87 | + bool scheduler;
|
|
| 88 | + bool gc;
|
|
| 89 | + bool nonmoving_gc;
|
|
| 90 | + bool spark_sampled;
|
|
| 91 | + bool spark_full;
|
|
| 92 | + bool user;
|
|
| 93 | + bool cap;
|
|
| 94 | +} RUNTIME_TRACE_FLAG_CACHE;
|
|
| 95 | + |
|
| 96 | +/*
|
|
| 97 | + * These flags should be used to determine whether or not some value should
|
|
| 98 | + * be traced at runtime, rather than the values in RtsFlags. These flags can
|
|
| 99 | + * be modified at runtime using setTraceFlag in `rts/EventLogWriter.h`.
|
|
| 100 | + */
|
|
| 101 | +extern RUNTIME_TRACE_FLAG_CACHE RuntimeTraceFlagCache;
|
|
| 83 | 102 | |
| 84 | 103 | // -----------------------------------------------------------------------------
|
| 85 | 104 | // Posting events
|
| ... | ... | @@ -136,6 +155,52 @@ void traceGcEvent_ (Capability *cap, EventTypeNum tag); |
| 136 | 155 | |
| 137 | 156 | void traceGcEventAtT_ (Capability *cap, StgWord64 ts, EventTypeNum tag);
|
| 138 | 157 | |
| 158 | +/*
|
|
| 159 | + * Record a nonmoving GC event.
|
|
| 160 | + */
|
|
| 161 | +#define traceConcMarkBegin() \
|
|
| 162 | + if (RTS_UNLIKELY(TRACE_nonmoving_gc)) { \
|
|
| 163 | + traceNonmovingGcEvent_(EVENT_CONC_MARK_BEGIN); \
|
|
| 164 | + }
|
|
| 165 | +#define traceConcMarkEnd(marked_obj_count) \
|
|
| 166 | + if (RTS_UNLIKELY(TRACE_nonmoving_gc)) { \
|
|
| 167 | + traceConcMarkEnd_(marked_obj_count); \
|
|
| 168 | + }
|
|
| 169 | +#define traceConcSyncBegin() \
|
|
| 170 | + if (RTS_UNLIKELY(TRACE_nonmoving_gc)) { \
|
|
| 171 | + traceNonmovingGcEvent_(EVENT_CONC_SYNC_BEGIN); \
|
|
| 172 | + }
|
|
| 173 | +#define traceConcSyncEnd() \
|
|
| 174 | + if (RTS_UNLIKELY(TRACE_nonmoving_gc)) { \
|
|
| 175 | + traceNonmovingGcEvent_(EVENT_CONC_SYNC_END); \
|
|
| 176 | + }
|
|
| 177 | +#define traceConcSweepBegin() \
|
|
| 178 | + if (RTS_UNLIKELY(TRACE_nonmoving_gc)) { \
|
|
| 179 | + traceNonmovingGcEvent_(EVENT_CONC_SWEEP_BEGIN); \
|
|
| 180 | + }
|
|
| 181 | +#define traceConcSweepEnd() \
|
|
| 182 | + if (RTS_UNLIKELY(TRACE_nonmoving_gc)) { \
|
|
| 183 | + traceNonmovingGcEvent_(EVENT_CONC_SWEEP_END); \
|
|
| 184 | + }
|
|
| 185 | +#define traceConcUpdRemSetFlush(cap) \
|
|
| 186 | + if (RTS_UNLIKELY(TRACE_nonmoving_gc)) { \
|
|
| 187 | + traceConcUpdRemSetFlush_(cap); \
|
|
| 188 | + }
|
|
| 189 | +#define traceNonmovingHeapCensus(blk_size, census) \
|
|
| 190 | + if (RTS_UNLIKELY(TRACE_nonmoving_gc)) { \
|
|
| 191 | + traceNonmovingHeapCensus_(blk_size, census); \
|
|
| 192 | + }
|
|
| 193 | +#define traceNonmovingPrunedSegments(pruned_segments, free_segments) \
|
|
| 194 | + if (RTS_UNLIKELY(TRACE_nonmoving_gc)) { \
|
|
| 195 | + traceNonmovingPrunedSegments_(pruned_segments, free_segments); \
|
|
| 196 | + }
|
|
| 197 | + |
|
| 198 | +void traceNonmovingGcEvent_ (EventTypeNum tag);
|
|
| 199 | +void traceConcMarkEnd_(StgWord32 marked_obj_count);
|
|
| 200 | +void traceConcUpdRemSetFlush_(Capability *cap);
|
|
| 201 | +void traceNonmovingHeapCensus_(uint16_t blk_size, const struct NonmovingAllocCensus *census);
|
|
| 202 | +void traceNonmovingPrunedSegments_(uint32_t pruned_segments, uint32_t free_segments);
|
|
| 203 | + |
|
| 139 | 204 | /*
|
| 140 | 205 | * Record a heap event
|
| 141 | 206 | */
|
| ... | ... | @@ -321,17 +386,6 @@ void traceProfSampleCostCentre(Capability *cap, |
| 321 | 386 | void traceProfBegin(void);
|
| 322 | 387 | #endif /* PROFILING */
|
| 323 | 388 | |
| 324 | -void traceConcMarkBegin(void);
|
|
| 325 | -void traceConcMarkEnd(StgWord32 marked_obj_count);
|
|
| 326 | -void traceConcSyncBegin(void);
|
|
| 327 | -void traceConcSyncEnd(void);
|
|
| 328 | -void traceConcSweepBegin(void);
|
|
| 329 | -void traceConcSweepEnd(void);
|
|
| 330 | -void traceConcUpdRemSetFlush(Capability *cap);
|
|
| 331 | -void traceNonmovingHeapCensus(uint16_t blk_size,
|
|
| 332 | - const struct NonmovingAllocCensus *census);
|
|
| 333 | -void traceNonmovingPrunedSegments(uint32_t pruned_segments, uint32_t free_segments);
|
|
| 334 | - |
|
| 335 | 389 | void traceIPE(const InfoProvEnt *ipe);
|
| 336 | 390 | void flushTrace(void);
|
| 337 | 391 | |
| ... | ... | @@ -384,6 +438,7 @@ void flushTrace(void); |
| 384 | 438 | #define traceConcSweepEnd() /* nothing */
|
| 385 | 439 | #define traceConcUpdRemSetFlush(cap) /* nothing */
|
| 386 | 440 | #define traceNonmovingHeapCensus(blk_size, census) /* nothing */
|
| 441 | +#define traceNonmovingPrunedSegments(pruned_segments, free_segments) /* nothing */
|
|
| 387 | 442 | |
| 388 | 443 | #define flushTrace() /* nothing */
|
| 389 | 444 |
| ... | ... | @@ -78,3 +78,34 @@ void endEventLogging(void); |
| 78 | 78 | * Flush the eventlog. cap can be NULL if one is not held.
|
| 79 | 79 | */
|
| 80 | 80 | void flushEventLog(Capability **cap);
|
| 81 | + |
|
| 82 | +/*
|
|
| 83 | + * An enumeration for the runtime trace flags.
|
|
| 84 | + */
|
|
| 85 | +typedef enum {
|
|
| 86 | + TRACE_SCHEDULER,
|
|
| 87 | + TRACE_GC,
|
|
| 88 | + TRACE_NONMOVING_GC,
|
|
| 89 | + TRACE_SPARK_SAMPLED,
|
|
| 90 | + TRACE_SPARK_FULL,
|
|
| 91 | + TRACE_USER,
|
|
| 92 | + TRACE_CAP,
|
|
| 93 | +} RUNTIME_TRACE_FLAG;
|
|
| 94 | + |
|
| 95 | +/*
|
|
| 96 | + * Get the value of the given runtime trace flag.
|
|
| 97 | + *
|
|
| 98 | + * Warning: The trace flag cache is not thread-safe. After initialisation, the
|
|
| 99 | + * RTS never writes to these values, but concurrently using getTraceFlag and
|
|
| 100 | + * setTraceFlag for the same flag is a race condition.
|
|
| 101 | + */
|
|
| 102 | +bool getTraceFlag(RUNTIME_TRACE_FLAG flag);
|
|
| 103 | + |
|
| 104 | +/*
|
|
| 105 | + * Set the value of the given runtime trace flag.
|
|
| 106 | + *
|
|
| 107 | + * Warning: The trace flag cache is not thread-safe. After initialisation, the
|
|
| 108 | + * RTS never writes to these values. However, inconsistent reads may lead to
|
|
| 109 | + * incorrect tracing for a short time after setting a trace flag.
|
|
| 110 | + */
|
|
| 111 | +void setTraceFlag(RUNTIME_TRACE_FLAG flag, bool value); |
| ... | ... | @@ -1339,7 +1339,7 @@ concurrent_marking: |
| 1339 | 1339 | nonmovingPrintAllocatorCensus(!concurrent);
|
| 1340 | 1340 | #endif
|
| 1341 | 1341 | #if defined(TRACING)
|
| 1342 | - if (RtsFlags.TraceFlags.nonmoving_gc)
|
|
| 1342 | + if (RTS_UNLIKELY(TRACE_nonmoving_gc))
|
|
| 1343 | 1343 | nonmovingTraceAllocatorCensus();
|
| 1344 | 1344 | #endif
|
| 1345 | 1345 |