Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC

Commits:

6 changed files:

Changes:

  • changelog.d/dynamic-trace-flags
    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
    +}

  • rts/RtsSymbols.c
    ... ... @@ -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)                                         \
    

  • rts/Trace.c
    ... ... @@ -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)
    

  • rts/Trace.h
    ... ... @@ -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
     
    

  • rts/include/rts/EventLogWriter.h
    ... ... @@ -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);

  • rts/sm/NonMoving.c
    ... ... @@ -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