Duncan Coutts pushed to branch wip/dcoutts/issue-27105-stopTicker-2 at Glasgow Haskell Compiler / GHC

Commits:

5 changed files:

Changes:

  • rts/Capability.c
    ... ... @@ -443,13 +443,6 @@ void
    443 443
     moreCapabilities (uint32_t from USED_IF_THREADS, uint32_t to USED_IF_THREADS)
    
    444 444
     {
    
    445 445
     #if defined(THREADED_RTS)
    
    446
    -    // We must disable the timer while we do this since the tick handler may
    
    447
    -    // call contextSwitchAllCapabilities, which may see the capabilities array
    
    448
    -    // as we free it. The alternative would be to protect the capabilities
    
    449
    -    // array with a lock but this seems more expensive than necessary.
    
    450
    -    // See #17289.
    
    451
    -    stopTimer();
    
    452
    -
    
    453 446
         if (to == 1) {
    
    454 447
             // THREADED_RTS must work on builds that don't have a mutable
    
    455 448
             // BaseReg (eg. unregisterised), so in this case
    
    ... ... @@ -470,8 +463,6 @@ moreCapabilities (uint32_t from USED_IF_THREADS, uint32_t to USED_IF_THREADS)
    470 463
         }
    
    471 464
     
    
    472 465
         debugTrace(DEBUG_sched, "allocated %d more capabilities", to - from);
    
    473
    -
    
    474
    -    startTimer();
    
    475 466
     #endif
    
    476 467
     }
    
    477 468
     
    

  • rts/Schedule.c
    ... ... @@ -37,6 +37,7 @@
    37 37
     #include "win32/AsyncWinIO.h"
    
    38 38
     #endif
    
    39 39
     #include "Trace.h"
    
    40
    +#include "eventlog/EventLog.h"
    
    40 41
     #include "RaiseAsync.h"
    
    41 42
     #include "Threads.h"
    
    42 43
     #include "Timer.h"
    
    ... ... @@ -2100,24 +2101,31 @@ forkProcess(HsStablePtr *entry
    2100 2101
         ACQUIRE_LOCK(&all_tasks_mutex);
    
    2101 2102
     #endif
    
    2102 2103
     
    
    2103
    -    stopTimer(); // See #4074
    
    2104
    -
    
    2105 2104
     #if defined(TRACING)
    
    2106
    -    flushAllCapsEventsBufs(); // so that child won't inherit dirty file buffers
    
    2105
    +#if defined(HAVE_PREEMPTION)
    
    2106
    +    // We must hold the eventlog global mutex over the fork to prevent the
    
    2107
    +    // timer thread from trying to post events. While holding the mutex we need
    
    2108
    +    // to flush the eventlogs (global and per-cap) so that child won't inherit
    
    2109
    +    // dirty eventlog buffers or file buffers.
    
    2110
    +    ACQUIRE_LOCK_ALWAYS(&eventBufMutex);
    
    2111
    +#endif
    
    2112
    +    flushAllCapsEventsBufs_();
    
    2107 2113
     #endif
    
    2108 2114
     
    
    2109 2115
         pid = fork();
    
    2110 2116
     
    
    2111 2117
         if (pid) { // parent
    
    2112 2118
     
    
    2113
    -        startTimer(); // #4074
    
    2114
    -
    
    2115 2119
             RELEASE_LOCK(&sched_mutex);
    
    2116 2120
             RELEASE_LOCK(&sm_mutex);
    
    2117 2121
             RELEASE_LOCK(&stable_ptr_mutex);
    
    2118 2122
             RELEASE_LOCK(&stable_name_mutex);
    
    2119 2123
             RELEASE_LOCK(&task->lock);
    
    2120 2124
     
    
    2125
    +#if defined(TRACING) && defined(HAVE_PREEMPTION)
    
    2126
    +        RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    2127
    +#endif
    
    2128
    +
    
    2121 2129
     #if defined(THREADED_RTS)
    
    2122 2130
             /* N.B. releaseCapability_ below may need to take all_tasks_mutex */
    
    2123 2131
             RELEASE_LOCK(&all_tasks_mutex);
    
    ... ... @@ -2303,12 +2311,6 @@ setNumCapabilities (uint32_t new_n_capabilities USED_IF_THREADS)
    2303 2311
         cap = rts_lock();
    
    2304 2312
         task = cap->running_task;
    
    2305 2313
     
    
    2306
    -
    
    2307
    -    // N.B. We must stop the interval timer while we are changing the
    
    2308
    -    // capabilities array lest handle_tick may try to context switch
    
    2309
    -    // an old capability. See #17289.
    
    2310
    -    stopTimer();
    
    2311
    -
    
    2312 2314
         stopAllCapabilities(&cap, task);
    
    2313 2315
     
    
    2314 2316
         if (new_n_capabilities < enabled_capabilities)
    
    ... ... @@ -2364,9 +2366,7 @@ setNumCapabilities (uint32_t new_n_capabilities USED_IF_THREADS)
    2364 2366
                 tracingAddCapabilities(n_capabilities, new_n_capabilities);
    
    2365 2367
     #endif
    
    2366 2368
     
    
    2367
    -            // Resize the capabilities array
    
    2368
    -            // NB. after this, capabilities points somewhere new.  Any pointers
    
    2369
    -            // of type (Capability *) are now invalid.
    
    2369
    +            // Allocate and initialise the extra capabilities
    
    2370 2370
                 moreCapabilities(n_capabilities, new_n_capabilities);
    
    2371 2371
     
    
    2372 2372
                 // Resize and update storage manager data structures
    
    ... ... @@ -2394,8 +2394,6 @@ setNumCapabilities (uint32_t new_n_capabilities USED_IF_THREADS)
    2394 2394
         // Notify IO manager that the number of capabilities has changed.
    
    2395 2395
         notifyIOManagerCapabilitiesChanged(&cap);
    
    2396 2396
     
    
    2397
    -    startTimer();
    
    2398
    -
    
    2399 2397
         rts_unlock(cap);
    
    2400 2398
     
    
    2401 2399
     #endif // THREADED_RTS
    

  • rts/eventlog/EventLog.c
    ... ... @@ -129,8 +129,11 @@ typedef struct _EventsBuf {
    129 129
     static EventsBuf *capEventBuf; // one EventsBuf for each Capability
    
    130 130
     
    
    131 131
     static EventsBuf eventBuf; // an EventsBuf not associated with any Capability
    
    132
    -#if defined(THREADED_RTS)
    
    133
    -static Mutex eventBufMutex; // protected by this mutex
    
    132
    +#if defined(HAVE_PREEMPTION)
    
    133
    +// Note that this mutex is used even in the non-threaded RTS, since the timer
    
    134
    +// thread posts events and flushes. So _all_ uses of this mutex must use
    
    135
    +// ACQUIRE_LOCK_ALWAYS/RELEASE_LOCK_ALWAYS.
    
    136
    +Mutex eventBufMutex; // protects eventBuf above
    
    134 137
     #endif
    
    135 138
     
    
    136 139
     // Event type
    
    ... ... @@ -393,8 +396,10 @@ initEventLogging(void)
    393 396
         moreCapEventBufs(0, get_n_capabilities());
    
    394 397
     
    
    395 398
         initEventsBuf(&eventBuf, EVENT_LOG_SIZE, (EventCapNo)(-1));
    
    396
    -#if defined(THREADED_RTS)
    
    399
    +#if defined(HAVE_PREEMPTION)
    
    397 400
         initMutex(&eventBufMutex);
    
    401
    +#endif
    
    402
    +#if defined(THREADED_RTS)
    
    398 403
         initMutex(&state_change_mutex);
    
    399 404
     #endif
    
    400 405
     }
    
    ... ... @@ -416,7 +421,7 @@ startEventLogging_(void)
    416 421
     {
    
    417 422
         initEventLogWriter();
    
    418 423
     
    
    419
    -    ACQUIRE_LOCK(&eventBufMutex);
    
    424
    +    ACQUIRE_LOCK_ALWAYS(&eventBufMutex);
    
    420 425
         postHeaderEvents();
    
    421 426
     
    
    422 427
         /*
    
    ... ... @@ -425,7 +430,7 @@ startEventLogging_(void)
    425 430
          */
    
    426 431
         printAndClearEventBuf(&eventBuf);
    
    427 432
     
    
    428
    -    RELEASE_LOCK(&eventBufMutex);
    
    433
    +    RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    429 434
     
    
    430 435
         return true;
    
    431 436
     }
    
    ... ... @@ -495,7 +500,7 @@ endEventLogging(void)
    495 500
     
    
    496 501
         flushEventLog_(NULL);
    
    497 502
     
    
    498
    -    ACQUIRE_LOCK(&eventBufMutex);
    
    503
    +    ACQUIRE_LOCK_ALWAYS(&eventBufMutex);
    
    499 504
     
    
    500 505
         // Mark end of events (data).
    
    501 506
         postEventTypeNum(&eventBuf, EVENT_DATA_END);
    
    ... ... @@ -503,7 +508,7 @@ endEventLogging(void)
    503 508
         // Flush the end of data marker.
    
    504 509
         printAndClearEventBuf(&eventBuf);
    
    505 510
     
    
    506
    -    RELEASE_LOCK(&eventBufMutex);
    
    511
    +    RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    507 512
     
    
    508 513
         stopEventLogWriter();
    
    509 514
         event_log_writer = NULL;
    
    ... ... @@ -666,7 +671,7 @@ void
    666 671
     postCapEvent (EventTypeNum  tag,
    
    667 672
                   EventCapNo    capno)
    
    668 673
     {
    
    669
    -    ACQUIRE_LOCK(&eventBufMutex);
    
    674
    +    ACQUIRE_LOCK_ALWAYS(&eventBufMutex);
    
    670 675
         ensureRoomForEvent(&eventBuf, tag);
    
    671 676
     
    
    672 677
         postEventHeader(&eventBuf, tag);
    
    ... ... @@ -685,14 +690,14 @@ postCapEvent (EventTypeNum tag,
    685 690
             barf("postCapEvent: unknown event tag %d", tag);
    
    686 691
         }
    
    687 692
     
    
    688
    -    RELEASE_LOCK(&eventBufMutex);
    
    693
    +    RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    689 694
     }
    
    690 695
     
    
    691 696
     void postCapsetEvent (EventTypeNum tag,
    
    692 697
                           EventCapsetID capset,
    
    693 698
                           StgWord info)
    
    694 699
     {
    
    695
    -    ACQUIRE_LOCK(&eventBufMutex);
    
    700
    +    ACQUIRE_LOCK_ALWAYS(&eventBufMutex);
    
    696 701
         ensureRoomForEvent(&eventBuf, tag);
    
    697 702
     
    
    698 703
         postEventHeader(&eventBuf, tag);
    
    ... ... @@ -726,7 +731,7 @@ void postCapsetEvent (EventTypeNum tag,
    726 731
             barf("postCapsetEvent: unknown event tag %d", tag);
    
    727 732
         }
    
    728 733
     
    
    729
    -    RELEASE_LOCK(&eventBufMutex);
    
    734
    +    RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    730 735
     }
    
    731 736
     
    
    732 737
     void postCapsetStrEvent (EventTypeNum tag,
    
    ... ... @@ -740,14 +745,14 @@ void postCapsetStrEvent (EventTypeNum tag,
    740 745
             return;
    
    741 746
         }
    
    742 747
     
    
    743
    -    ACQUIRE_LOCK(&eventBufMutex);
    
    748
    +    ACQUIRE_LOCK_ALWAYS(&eventBufMutex);
    
    744 749
     
    
    745 750
         if (!hasRoomForVariableEvent(&eventBuf, size)){
    
    746 751
             printAndClearEventBuf(&eventBuf);
    
    747 752
     
    
    748 753
             if (!hasRoomForVariableEvent(&eventBuf, size)){
    
    749 754
                 errorBelch("Event size exceeds buffer size, bail out");
    
    750
    -            RELEASE_LOCK(&eventBufMutex);
    
    755
    +            RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    751 756
                 return;
    
    752 757
             }
    
    753 758
         }
    
    ... ... @@ -758,7 +763,7 @@ void postCapsetStrEvent (EventTypeNum tag,
    758 763
     
    
    759 764
         postBuf(&eventBuf, (StgWord8*) msg, strsize);
    
    760 765
     
    
    761
    -    RELEASE_LOCK(&eventBufMutex);
    
    766
    +    RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    762 767
     }
    
    763 768
     
    
    764 769
     void postCapsetVecEvent (EventTypeNum tag,
    
    ... ... @@ -783,14 +788,14 @@ void postCapsetVecEvent (EventTypeNum tag,
    783 788
             }
    
    784 789
         }
    
    785 790
     
    
    786
    -    ACQUIRE_LOCK(&eventBufMutex);
    
    791
    +    ACQUIRE_LOCK_ALWAYS(&eventBufMutex);
    
    787 792
     
    
    788 793
         if (!hasRoomForVariableEvent(&eventBuf, size)){
    
    789 794
             printAndClearEventBuf(&eventBuf);
    
    790 795
     
    
    791 796
             if(!hasRoomForVariableEvent(&eventBuf, size)){
    
    792 797
                 errorBelch("Event size exceeds buffer size, bail out");
    
    793
    -            RELEASE_LOCK(&eventBufMutex);
    
    798
    +            RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    794 799
                 return;
    
    795 800
             }
    
    796 801
         }
    
    ... ... @@ -804,7 +809,7 @@ void postCapsetVecEvent (EventTypeNum tag,
    804 809
             postBuf(&eventBuf, (StgWord8*) argv[i], 1 + strlen(argv[i]));
    
    805 810
         }
    
    806 811
     
    
    807
    -    RELEASE_LOCK(&eventBufMutex);
    
    812
    +    RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    808 813
     }
    
    809 814
     
    
    810 815
     void postWallClockTime (EventCapsetID capset)
    
    ... ... @@ -813,7 +818,7 @@ void postWallClockTime (EventCapsetID capset)
    813 818
         StgWord64 sec;
    
    814 819
         StgWord32 nsec;
    
    815 820
     
    
    816
    -    ACQUIRE_LOCK(&eventBufMutex);
    
    821
    +    ACQUIRE_LOCK_ALWAYS(&eventBufMutex);
    
    817 822
     
    
    818 823
         /* The EVENT_WALL_CLOCK_TIME event is intended to allow programs
    
    819 824
            reading the eventlog to match up the event timestamps with wall
    
    ... ... @@ -846,7 +851,7 @@ void postWallClockTime (EventCapsetID capset)
    846 851
         postWord64(&eventBuf, sec);
    
    847 852
         postWord32(&eventBuf, nsec);
    
    848 853
     
    
    849
    -    RELEASE_LOCK(&eventBufMutex);
    
    854
    +    RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    850 855
     }
    
    851 856
     
    
    852 857
     /*
    
    ... ... @@ -885,7 +890,7 @@ void postEventHeapInfo (EventCapsetID heap_capset,
    885 890
                             W_          mblockSize,
    
    886 891
                             W_          blockSize)
    
    887 892
     {
    
    888
    -    ACQUIRE_LOCK(&eventBufMutex);
    
    893
    +    ACQUIRE_LOCK_ALWAYS(&eventBufMutex);
    
    889 894
         ensureRoomForEvent(&eventBuf, EVENT_HEAP_INFO_GHC);
    
    890 895
     
    
    891 896
         postEventHeader(&eventBuf, EVENT_HEAP_INFO_GHC);
    
    ... ... @@ -899,7 +904,7 @@ void postEventHeapInfo (EventCapsetID heap_capset,
    899 904
         postWord64(&eventBuf, mblockSize);
    
    900 905
         postWord64(&eventBuf, blockSize);
    
    901 906
     
    
    902
    -    RELEASE_LOCK(&eventBufMutex);
    
    907
    +    RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    903 908
     }
    
    904 909
     
    
    905 910
     void postEventGcStats  (Capability    *cap,
    
    ... ... @@ -952,7 +957,7 @@ void postTaskCreateEvent (EventTaskId taskId,
    952 957
                               EventCapNo capno,
    
    953 958
                               EventKernelThreadId tid)
    
    954 959
     {
    
    955
    -    ACQUIRE_LOCK(&eventBufMutex);
    
    960
    +    ACQUIRE_LOCK_ALWAYS(&eventBufMutex);
    
    956 961
         ensureRoomForEvent(&eventBuf, EVENT_TASK_CREATE);
    
    957 962
     
    
    958 963
         postEventHeader(&eventBuf, EVENT_TASK_CREATE);
    
    ... ... @@ -961,14 +966,14 @@ void postTaskCreateEvent (EventTaskId taskId,
    961 966
         postCapNo(&eventBuf, capno);
    
    962 967
         postKernelThreadId(&eventBuf, tid);
    
    963 968
     
    
    964
    -    RELEASE_LOCK(&eventBufMutex);
    
    969
    +    RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    965 970
     }
    
    966 971
     
    
    967 972
     void postTaskMigrateEvent (EventTaskId taskId,
    
    968 973
                                EventCapNo capno,
    
    969 974
                                EventCapNo new_capno)
    
    970 975
     {
    
    971
    -    ACQUIRE_LOCK(&eventBufMutex);
    
    976
    +    ACQUIRE_LOCK_ALWAYS(&eventBufMutex);
    
    972 977
         ensureRoomForEvent(&eventBuf, EVENT_TASK_MIGRATE);
    
    973 978
     
    
    974 979
         postEventHeader(&eventBuf, EVENT_TASK_MIGRATE);
    
    ... ... @@ -977,28 +982,28 @@ void postTaskMigrateEvent (EventTaskId taskId,
    977 982
         postCapNo(&eventBuf, capno);
    
    978 983
         postCapNo(&eventBuf, new_capno);
    
    979 984
     
    
    980
    -    RELEASE_LOCK(&eventBufMutex);
    
    985
    +    RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    981 986
     }
    
    982 987
     
    
    983 988
     void postTaskDeleteEvent (EventTaskId taskId)
    
    984 989
     {
    
    985
    -    ACQUIRE_LOCK(&eventBufMutex);
    
    990
    +    ACQUIRE_LOCK_ALWAYS(&eventBufMutex);
    
    986 991
         ensureRoomForEvent(&eventBuf, EVENT_TASK_DELETE);
    
    987 992
     
    
    988 993
         postEventHeader(&eventBuf, EVENT_TASK_DELETE);
    
    989 994
         /* EVENT_TASK_DELETE (taskID) */
    
    990 995
         postTaskId(&eventBuf, taskId);
    
    991 996
     
    
    992
    -    RELEASE_LOCK(&eventBufMutex);
    
    997
    +    RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    993 998
     }
    
    994 999
     
    
    995 1000
     void
    
    996 1001
     postEventNoCap (EventTypeNum tag)
    
    997 1002
     {
    
    998
    -    ACQUIRE_LOCK(&eventBufMutex);
    
    1003
    +    ACQUIRE_LOCK_ALWAYS(&eventBufMutex);
    
    999 1004
         ensureRoomForEvent(&eventBuf, tag);
    
    1000 1005
         postEventHeader(&eventBuf, tag);
    
    1001
    -    RELEASE_LOCK(&eventBufMutex);
    
    1006
    +    RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    1002 1007
     }
    
    1003 1008
     
    
    1004 1009
     void
    
    ... ... @@ -1042,9 +1047,9 @@ void postLogMsg(EventsBuf *eb, EventTypeNum type, char *msg, va_list ap)
    1042 1047
     
    
    1043 1048
     void postMsg(char *msg, va_list ap)
    
    1044 1049
     {
    
    1045
    -    ACQUIRE_LOCK(&eventBufMutex);
    
    1050
    +    ACQUIRE_LOCK_ALWAYS(&eventBufMutex);
    
    1046 1051
         postLogMsg(&eventBuf, EVENT_LOG_MSG, msg, ap);
    
    1047
    -    RELEASE_LOCK(&eventBufMutex);
    
    1052
    +    RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    1048 1053
     }
    
    1049 1054
     
    
    1050 1055
     void postCapMsg(Capability *cap, char *msg, va_list ap)
    
    ... ... @@ -1138,32 +1143,32 @@ void postConcUpdRemSetFlush(Capability *cap)
    1138 1143
     
    
    1139 1144
     void postConcMarkEnd(StgWord32 marked_obj_count)
    
    1140 1145
     {
    
    1141
    -    ACQUIRE_LOCK(&eventBufMutex);
    
    1146
    +    ACQUIRE_LOCK_ALWAYS(&eventBufMutex);
    
    1142 1147
         ensureRoomForEvent(&eventBuf, EVENT_CONC_MARK_END);
    
    1143 1148
         postEventHeader(&eventBuf, EVENT_CONC_MARK_END);
    
    1144 1149
         postWord32(&eventBuf, marked_obj_count);
    
    1145
    -    RELEASE_LOCK(&eventBufMutex);
    
    1150
    +    RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    1146 1151
     }
    
    1147 1152
     
    
    1148 1153
     void postNonmovingHeapCensus(uint16_t blk_size,
    
    1149 1154
                                  const struct NonmovingAllocCensus *census)
    
    1150 1155
     {
    
    1151
    -    ACQUIRE_LOCK(&eventBufMutex);
    
    1156
    +    ACQUIRE_LOCK_ALWAYS(&eventBufMutex);
    
    1152 1157
         postEventHeader(&eventBuf, EVENT_NONMOVING_HEAP_CENSUS);
    
    1153 1158
         postWord16(&eventBuf, blk_size);
    
    1154 1159
         postWord32(&eventBuf, census->n_active_segs);
    
    1155 1160
         postWord32(&eventBuf, census->n_filled_segs);
    
    1156 1161
         postWord32(&eventBuf, census->n_live_blocks);
    
    1157
    -    RELEASE_LOCK(&eventBufMutex);
    
    1162
    +    RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    1158 1163
     }
    
    1159 1164
     
    
    1160 1165
     void postNonmovingPrunedSegments(uint32_t pruned_segments, uint32_t free_segments)
    
    1161 1166
     {
    
    1162
    -    ACQUIRE_LOCK(&eventBufMutex);
    
    1167
    +    ACQUIRE_LOCK_ALWAYS(&eventBufMutex);
    
    1163 1168
         postEventHeader(&eventBuf, EVENT_NONMOVING_PRUNED_SEGMENTS);
    
    1164 1169
         postWord32(&eventBuf, pruned_segments);
    
    1165 1170
         postWord32(&eventBuf, free_segments);
    
    1166
    -    RELEASE_LOCK(&eventBufMutex);
    
    1171
    +    RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    1167 1172
     }
    
    1168 1173
     
    
    1169 1174
     void closeBlockMarker (EventsBuf *ebuf)
    
    ... ... @@ -1224,7 +1229,7 @@ static HeapProfBreakdown getHeapProfBreakdown(void)
    1224 1229
     
    
    1225 1230
     void postHeapProfBegin(void)
    
    1226 1231
     {
    
    1227
    -    ACQUIRE_LOCK(&eventBufMutex);
    
    1232
    +    ACQUIRE_LOCK_ALWAYS(&eventBufMutex);
    
    1228 1233
         PROFILING_FLAGS *flags = &RtsFlags.ProfFlags;
    
    1229 1234
         StgWord modSelector_len   =
    
    1230 1235
             flags->modSelector ? strlen(flags->modSelector) : 0;
    
    ... ... @@ -1258,42 +1263,42 @@ void postHeapProfBegin(void)
    1258 1263
         postStringLen(&eventBuf, flags->ccsSelector, ccsSelector_len);
    
    1259 1264
         postStringLen(&eventBuf, flags->retainerSelector, retainerSelector_len);
    
    1260 1265
         postStringLen(&eventBuf, flags->bioSelector, bioSelector_len);
    
    1261
    -    RELEASE_LOCK(&eventBufMutex);
    
    1266
    +    RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    1262 1267
     }
    
    1263 1268
     
    
    1264 1269
     void postHeapProfSampleBegin(StgInt era)
    
    1265 1270
     {
    
    1266
    -    ACQUIRE_LOCK(&eventBufMutex);
    
    1271
    +    ACQUIRE_LOCK_ALWAYS(&eventBufMutex);
    
    1267 1272
         ensureRoomForEvent(&eventBuf, EVENT_HEAP_PROF_SAMPLE_BEGIN);
    
    1268 1273
         postEventHeader(&eventBuf, EVENT_HEAP_PROF_SAMPLE_BEGIN);
    
    1269 1274
         postWord64(&eventBuf, era);
    
    1270
    -    RELEASE_LOCK(&eventBufMutex);
    
    1275
    +    RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    1271 1276
     }
    
    1272 1277
     
    
    1273 1278
     
    
    1274 1279
     void postHeapBioProfSampleBegin(StgInt era, StgWord64 time)
    
    1275 1280
     {
    
    1276
    -    ACQUIRE_LOCK(&eventBufMutex);
    
    1281
    +    ACQUIRE_LOCK_ALWAYS(&eventBufMutex);
    
    1277 1282
         ensureRoomForEvent(&eventBuf, EVENT_HEAP_BIO_PROF_SAMPLE_BEGIN);
    
    1278 1283
         postEventHeader(&eventBuf, EVENT_HEAP_BIO_PROF_SAMPLE_BEGIN);
    
    1279 1284
         postWord64(&eventBuf, era);
    
    1280 1285
         postWord64(&eventBuf, time);
    
    1281
    -    RELEASE_LOCK(&eventBufMutex);
    
    1286
    +    RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    1282 1287
     }
    
    1283 1288
     
    
    1284 1289
     void postHeapProfSampleEnd(StgInt era)
    
    1285 1290
     {
    
    1286
    -    ACQUIRE_LOCK(&eventBufMutex);
    
    1291
    +    ACQUIRE_LOCK_ALWAYS(&eventBufMutex);
    
    1287 1292
         ensureRoomForEvent(&eventBuf, EVENT_HEAP_PROF_SAMPLE_END);
    
    1288 1293
         postEventHeader(&eventBuf, EVENT_HEAP_PROF_SAMPLE_END);
    
    1289 1294
         postWord64(&eventBuf, era);
    
    1290
    -    RELEASE_LOCK(&eventBufMutex);
    
    1295
    +    RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    1291 1296
     }
    
    1292 1297
     
    
    1293 1298
     void postHeapProfSampleString(const char *label,
    
    1294 1299
                                   StgWord64 residency)
    
    1295 1300
     {
    
    1296
    -    ACQUIRE_LOCK(&eventBufMutex);
    
    1301
    +    ACQUIRE_LOCK_ALWAYS(&eventBufMutex);
    
    1297 1302
         StgWord label_len = strlen(label);
    
    1298 1303
         StgWord len = 1+8+label_len+1;
    
    1299 1304
         CHECK(!ensureRoomForVariableEvent(&eventBuf, len));
    
    ... ... @@ -1303,7 +1308,7 @@ void postHeapProfSampleString(const char *label,
    1303 1308
         postWord8(&eventBuf, 0);
    
    1304 1309
         postWord64(&eventBuf, residency);
    
    1305 1310
         postStringLen(&eventBuf, label, label_len);
    
    1306
    -    RELEASE_LOCK(&eventBufMutex);
    
    1311
    +    RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    1307 1312
     }
    
    1308 1313
     
    
    1309 1314
     #if defined(PROFILING)
    
    ... ... @@ -1313,7 +1318,7 @@ void postHeapProfCostCentre(StgWord32 ccID,
    1313 1318
                                 const char *srcloc,
    
    1314 1319
                                 StgBool is_caf)
    
    1315 1320
     {
    
    1316
    -    ACQUIRE_LOCK(&eventBufMutex);
    
    1321
    +    ACQUIRE_LOCK_ALWAYS(&eventBufMutex);
    
    1317 1322
         StgWord label_len = strlen(label);
    
    1318 1323
         StgWord module_len = strlen(module);
    
    1319 1324
         StgWord srcloc_len = strlen(srcloc);
    
    ... ... @@ -1326,13 +1331,13 @@ void postHeapProfCostCentre(StgWord32 ccID,
    1326 1331
         postStringLen(&eventBuf, module, module_len);
    
    1327 1332
         postStringLen(&eventBuf, srcloc, srcloc_len);
    
    1328 1333
         postWord8(&eventBuf, is_caf);
    
    1329
    -    RELEASE_LOCK(&eventBufMutex);
    
    1334
    +    RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    1330 1335
     }
    
    1331 1336
     
    
    1332 1337
     void postHeapProfSampleCostCentre(CostCentreStack *stack,
    
    1333 1338
                                       StgWord64 residency)
    
    1334 1339
     {
    
    1335
    -    ACQUIRE_LOCK(&eventBufMutex);
    
    1340
    +    ACQUIRE_LOCK_ALWAYS(&eventBufMutex);
    
    1336 1341
         StgWord depth = 0;
    
    1337 1342
         CostCentreStack *ccs;
    
    1338 1343
         for (ccs = stack; ccs != NULL && ccs != CCS_MAIN; ccs = ccs->prevStack)
    
    ... ... @@ -1351,7 +1356,7 @@ void postHeapProfSampleCostCentre(CostCentreStack *stack,
    1351 1356
              depth>0 && ccs != NULL && ccs != CCS_MAIN;
    
    1352 1357
              ccs = ccs->prevStack, depth--)
    
    1353 1358
             postWord32(&eventBuf, ccs->cc->ccID);
    
    1354
    -    RELEASE_LOCK(&eventBufMutex);
    
    1359
    +    RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    1355 1360
     }
    
    1356 1361
     
    
    1357 1362
     
    
    ... ... @@ -1359,7 +1364,7 @@ void postProfSampleCostCentre(Capability *cap,
    1359 1364
                                   CostCentreStack *stack,
    
    1360 1365
                                   StgWord64 tick)
    
    1361 1366
     {
    
    1362
    -    ACQUIRE_LOCK(&eventBufMutex);
    
    1367
    +    ACQUIRE_LOCK_ALWAYS(&eventBufMutex);
    
    1363 1368
         StgWord depth = 0;
    
    1364 1369
         CostCentreStack *ccs;
    
    1365 1370
         for (ccs = stack; ccs != NULL && ccs != CCS_MAIN; ccs = ccs->prevStack)
    
    ... ... @@ -1377,7 +1382,7 @@ void postProfSampleCostCentre(Capability *cap,
    1377 1382
              depth>0 && ccs != NULL && ccs != CCS_MAIN;
    
    1378 1383
              ccs = ccs->prevStack, depth--)
    
    1379 1384
             postWord32(&eventBuf, ccs->cc->ccID);
    
    1380
    -    RELEASE_LOCK(&eventBufMutex);
    
    1385
    +    RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    1381 1386
     }
    
    1382 1387
     
    
    1383 1388
     // This event is output at the start of profiling so the tick interval can
    
    ... ... @@ -1385,11 +1390,11 @@ void postProfSampleCostCentre(Capability *cap,
    1385 1390
     // can be calculated from how many samples there are.
    
    1386 1391
     void postProfBegin(void)
    
    1387 1392
     {
    
    1388
    -    ACQUIRE_LOCK(&eventBufMutex);
    
    1393
    +    ACQUIRE_LOCK_ALWAYS(&eventBufMutex);
    
    1389 1394
         postEventHeader(&eventBuf, EVENT_PROF_BEGIN);
    
    1390 1395
         // The interval that each tick was sampled, in nanoseconds
    
    1391 1396
         postWord64(&eventBuf, TimeToNS(RtsFlags.MiscFlags.tickInterval));
    
    1392
    -    RELEASE_LOCK(&eventBufMutex);
    
    1397
    +    RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    1393 1398
     }
    
    1394 1399
     #endif /* PROFILING */
    
    1395 1400
     
    
    ... ... @@ -1415,11 +1420,11 @@ static void postTickyCounterDef(EventsBuf *eb, StgEntCounter *p)
    1415 1420
     
    
    1416 1421
     void postTickyCounterDefs(StgEntCounter *counters)
    
    1417 1422
     {
    
    1418
    -    ACQUIRE_LOCK(&eventBufMutex);
    
    1423
    +    ACQUIRE_LOCK_ALWAYS(&eventBufMutex);
    
    1419 1424
         for (StgEntCounter *p = counters; p != NULL; p = p->link) {
    
    1420 1425
             postTickyCounterDef(&eventBuf, p);
    
    1421 1426
         }
    
    1422
    -    RELEASE_LOCK(&eventBufMutex);
    
    1427
    +    RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    1423 1428
     }
    
    1424 1429
     
    
    1425 1430
     static void postTickyCounterSample(EventsBuf *eb, StgEntCounter *p)
    
    ... ... @@ -1443,13 +1448,13 @@ static void postTickyCounterSample(EventsBuf *eb, StgEntCounter *p)
    1443 1448
     
    
    1444 1449
     void postTickyCounterSamples(StgEntCounter *counters)
    
    1445 1450
     {
    
    1446
    -    ACQUIRE_LOCK(&eventBufMutex);
    
    1451
    +    ACQUIRE_LOCK_ALWAYS(&eventBufMutex);
    
    1447 1452
         ensureRoomForEvent(&eventBuf, EVENT_TICKY_COUNTER_SAMPLE);
    
    1448 1453
         postEventHeader(&eventBuf, EVENT_TICKY_COUNTER_BEGIN_SAMPLE);
    
    1449 1454
         for (StgEntCounter *p = counters; p != NULL; p = p->link) {
    
    1450 1455
             postTickyCounterSample(&eventBuf, p);
    
    1451 1456
         }
    
    1452
    -    RELEASE_LOCK(&eventBufMutex);
    
    1457
    +    RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    1453 1458
     }
    
    1454 1459
     #endif /* TICKY_TICKY */
    
    1455 1460
     void postIPE(const InfoProvEnt *ipe)
    
    ... ... @@ -1459,7 +1464,7 @@ void postIPE(const InfoProvEnt *ipe)
    1459 1464
     
    
    1460 1465
         // See Note [Maximum event length].
    
    1461 1466
         const StgWord MAX_IPE_STRING_LEN = 65535;
    
    1462
    -    ACQUIRE_LOCK(&eventBufMutex);
    
    1467
    +    ACQUIRE_LOCK_ALWAYS(&eventBufMutex);
    
    1463 1468
         StgWord table_name_len = MIN(strlen(ipe->prov.table_name), MAX_IPE_STRING_LEN);
    
    1464 1469
         StgWord closure_desc_len = MIN(strlen(closure_desc_buf), MAX_IPE_STRING_LEN);
    
    1465 1470
         StgWord ty_desc_len = MIN(strlen(ipe->prov.ty_desc), MAX_IPE_STRING_LEN);
    
    ... ... @@ -1489,7 +1494,7 @@ void postIPE(const InfoProvEnt *ipe)
    1489 1494
         postBuf(&eventBuf, &colon, 1);
    
    1490 1495
         postStringLen(&eventBuf, ipe->prov.src_span, src_span_len);
    
    1491 1496
     
    
    1492
    -    RELEASE_LOCK(&eventBufMutex);
    
    1497
    +    RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    1493 1498
     }
    
    1494 1499
     
    
    1495 1500
     void printAndClearEventBuf (EventsBuf *ebuf)
    
    ... ... @@ -1601,14 +1606,21 @@ void flushLocalEventsBuf(Capability *cap)
    1601 1606
     // Flush all capabilities' event buffers when we already hold all capabilities.
    
    1602 1607
     // Used during forkProcess.
    
    1603 1608
     void flushAllCapsEventsBufs(void)
    
    1609
    +{
    
    1610
    +    ACQUIRE_LOCK_ALWAYS(&eventBufMutex);
    
    1611
    +    flushAllCapsEventsBufs_();
    
    1612
    +    RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    1613
    +}
    
    1614
    +
    
    1615
    +// Unafe version that does not acquire/release eventBufMutex. You must
    
    1616
    +// already hold the eventBufMutex, which you must do with ACQUIRE_LOCK_ALWAYS!
    
    1617
    +void flushAllCapsEventsBufs_(void)
    
    1604 1618
     {
    
    1605 1619
         if (!event_log_writer) {
    
    1606 1620
             return;
    
    1607 1621
         }
    
    1608 1622
     
    
    1609
    -    ACQUIRE_LOCK(&eventBufMutex);
    
    1610 1623
         printAndClearEventBuf(&eventBuf);
    
    1611
    -    RELEASE_LOCK(&eventBufMutex);
    
    1612 1624
     
    
    1613 1625
         for (unsigned int i=0; i < getNumCapabilities(); i++) {
    
    1614 1626
             flushLocalEventsBuf(getCapability(i));
    
    ... ... @@ -1641,9 +1653,9 @@ static void flushEventLog_(Capability **cap USED_IF_THREADS)
    1641 1653
           return;
    
    1642 1654
         }
    
    1643 1655
     
    
    1644
    -    ACQUIRE_LOCK(&eventBufMutex);
    
    1656
    +    ACQUIRE_LOCK_ALWAYS(&eventBufMutex);
    
    1645 1657
         printAndClearEventBuf(&eventBuf);
    
    1646
    -    RELEASE_LOCK(&eventBufMutex);
    
    1658
    +    RELEASE_LOCK_ALWAYS(&eventBufMutex);
    
    1647 1659
     
    
    1648 1660
     #if defined(THREADED_RTS)
    
    1649 1661
         Task *task = newBoundTask();
    

  • rts/eventlog/EventLog.h
    ... ... @@ -18,6 +18,13 @@
    18 18
     #if defined(TRACING)
    
    19 19
     
    
    20 20
     extern bool eventlog_enabled;
    
    21
    +#if defined(HAVE_PREEMPTION)
    
    22
    +// Avoid using this mutex directly if at all possible. It is needed in the
    
    23
    +// implementation of forkProcess.
    
    24
    +//
    
    25
    +// All uses of this mutex must use ACQUIRE_LOCK_ALWAYS/RELEASE_LOCK_ALWAYS.
    
    26
    +extern Mutex eventBufMutex;
    
    27
    +#endif
    
    21 28
     
    
    22 29
     void initEventLogging(void);
    
    23 30
     void restartEventLogging(void);
    
    ... ... @@ -27,6 +34,7 @@ void abortEventLogging(void); // #4512 - after fork child needs to abort
    27 34
     void moreCapEventBufs (uint32_t from, uint32_t to);
    
    28 35
     void flushLocalEventsBuf(Capability *cap);
    
    29 36
     void flushAllCapsEventsBufs(void);
    
    37
    +void flushAllCapsEventsBufs_(void);
    
    30 38
     void flushAllEventsBufs(Capability *cap);
    
    31 39
     
    
    32 40
     typedef void (*EventlogInitPost)(void);
    

  • rts/include/rts/OSThreads.h
    ... ... @@ -244,9 +244,29 @@ extern bool timedWaitCondition ( Condition* pCond, Mutex* pMut, Time timeout)
    244 244
     //
    
    245 245
     // Mutexes
    
    246 246
     //
    
    247
    +// Even in the non-threaded RTS we use threads and mutexes! In particular the
    
    248
    +// timer/ticker is implemented using a thread. And using threads needs locks.
    
    249
    +// In particular we need locks for the data shared between the timer/ticker
    
    250
    +// thread and the thread running the main capability.
    
    251
    +#if defined(HAVE_PREEMPTION)
    
    247 252
     extern void initMutex             ( Mutex* pMut );
    
    248 253
     extern void closeMutex            ( Mutex* pMut );
    
    249 254
     
    
    255
    +// The "always" variants do locking in the threaded and non-threaded RTS.
    
    256
    +// The normal variants below are no-ops in the non-threaded RTS.
    
    257
    +#define ACQUIRE_LOCK_ALWAYS(l) OS_ACQUIRE_LOCK(l)
    
    258
    +#define TRY_ACQUIRE_LOCK_ALWAYS(l) OS_TRY_ACQUIRE_LOCK(l)
    
    259
    +#define RELEASE_LOCK_ALWAYS(l) OS_RELEASE_LOCK(l)
    
    260
    +#define ASSERT_LOCK_HELD_ALWAYS(l) OS_ASSERT_LOCK_HELD(l)
    
    261
    +#else
    
    262
    +// And just to be a bit confusing, the always variants are still no-ops when we
    
    263
    +// do not HAVE_PREEMPTION, since then we don't have threads or mutexes at all.
    
    264
    +#define ACQUIRE_LOCK_ALWAYS(l)
    
    265
    +#define TRY_ACQUIRE_LOCK_ALWAYS(l) 0
    
    266
    +#define RELEASE_LOCK_ALWAYS(l)
    
    267
    +#define ASSERT_LOCK_HELD_ALWAYS(l)
    
    268
    +#endif
    
    269
    +
    
    250 270
     // Processors and affinity
    
    251 271
     void setThreadAffinity (uint32_t n, uint32_t m);
    
    252 272
     void setThreadNode (uint32_t node);
    
    ... ... @@ -262,6 +282,7 @@ void releaseThreadNode (void);
    262 282
     
    
    263 283
     #else
    
    264 284
     
    
    285
    +// No-ops in the non-threaded RTS. See also the _ALWAYS variants above.
    
    265 286
     #define ACQUIRE_LOCK(l)
    
    266 287
     #define TRY_ACQUIRE_LOCK(l) 0
    
    267 288
     #define RELEASE_LOCK(l)