[Git][ghc/ghc][wip/T18043] rts: Flush eventlog buffers from flushEventLog

Ben Gamari gitlab at gitlab.haskell.org
Wed Apr 22 23:36:04 UTC 2020



Ben Gamari pushed to branch wip/T18043 at Glasgow Haskell Compiler / GHC


Commits:
9f8e0e9c by Ben Gamari at 2020-04-22T19:35:19-04:00
rts: Flush eventlog buffers from flushEventLog

As noted in #18043, flushTrace failed flush anything beyond the writer.
This means that a significant amount of data sitting in capability-local
event buffers may never get flushed, despite the users' pleads for us to
flush.

Fix this by making flushEventLog flush all of the event buffers before
flushing the writer.

Fixes #18043.

- - - - -


10 changed files:

- includes/RtsAPI.h
- includes/rts/EventLogWriter.h
- libraries/base/Debug/Trace.hs
- rts/Capability.c
- rts/Capability.h
- rts/Schedule.c
- rts/Trace.c
- rts/Trace.h
- rts/eventlog/EventLog.c
- rts/eventlog/EventLog.h


Changes:

=====================================
includes/RtsAPI.h
=====================================
@@ -17,7 +17,6 @@ extern "C" {
 
 #include "HsFFI.h"
 #include "rts/Time.h"
-#include "rts/EventLogWriter.h"
 
 /*
  * Running the scheduler
@@ -47,6 +46,9 @@ typedef struct CapabilityPublic_ {
     StgRegTable r;
 } CapabilityPublic;
 
+/* N.B. this needs the Capability declaration above. */
+#include "rts/EventLogWriter.h"
+
 /* ----------------------------------------------------------------------------
    RTS configuration settings, for passing to hs_init_ghc()
    ------------------------------------------------------------------------- */


=====================================
includes/rts/EventLogWriter.h
=====================================
@@ -64,3 +64,8 @@ bool startEventLogging(const EventLogWriter *writer);
  * Stop event logging and destroy the current EventLogWriter.
  */
 void endEventLogging(void);
+
+/*
+ * Flush the eventlog. cap can be NULL if one is not held.
+ */
+void flushEventLog(Capability **cap);


=====================================
libraries/base/Debug/Trace.hs
=====================================
@@ -37,6 +37,7 @@ module Debug.Trace (
         -- $eventlog_tracing
         traceEvent,
         traceEventIO,
+        flushEventLog,
 
         -- * Execution phase markers
         -- $markers
@@ -319,3 +320,11 @@ traceMarkerIO :: String -> IO ()
 traceMarkerIO msg =
   GHC.Foreign.withCString utf8 msg $ \(Ptr p) -> IO $ \s ->
     case traceMarker# p s of s' -> (# s', () #)
+
+-- | Immediately flush the event log, if enabled.
+--
+-- @since 4.15.0.0
+flushEventLog :: IO ()
+flushEventLog = c_flushEventLog nullPtr
+
+foreign import ccall "flushEventLog" c_flushEventLog :: Ptr () -> IO ()


=====================================
rts/Capability.c
=====================================
@@ -23,6 +23,7 @@
 #include "Schedule.h"
 #include "Sparks.h"
 #include "Trace.h"
+#include "eventlog/EventLog.h" // for flushLocalEventsBuf
 #include "sm/GC.h" // for gcWorkerThread()
 #include "STM.h"
 #include "RtsUtils.h"
@@ -885,6 +886,10 @@ yieldCapability (Capability** pCap, Task *task, bool gcAllowed)
                 debugTrace(DEBUG_nonmoving_gc, "Flushing update remembered set blocks...");
                 break;
 
+            case SYNC_FLUSH_EVENT_LOG:
+                flushLocalEventsBuf(cap);
+                break;
+
             default:
                 break;
             }


=====================================
rts/Capability.h
=====================================
@@ -263,7 +263,8 @@ typedef enum {
     SYNC_OTHER,
     SYNC_GC_SEQ,
     SYNC_GC_PAR,
-    SYNC_FLUSH_UPD_REM_SET
+    SYNC_FLUSH_UPD_REM_SET,
+    SYNC_FLUSH_EVENT_LOG
 } SyncType;
 
 //


=====================================
rts/Schedule.c
=====================================
@@ -2035,7 +2035,7 @@ forkProcess(HsStablePtr *entry
     stopTimer(); // See #4074
 
 #if defined(TRACING)
-    flushEventLog(); // so that child won't inherit dirty file buffers
+    flushAllCapsEventsBufs(); // so that child won't inherit dirty file buffers
 #endif
 
     pid = fork();


=====================================
rts/Trace.c
=====================================
@@ -117,10 +117,10 @@ void resetTracing (void)
     restartEventLogging();
 }
 
-void flushTrace (void)
+void flushTrace ()
 {
     if (eventlog_enabled) {
-        flushEventLog();
+        flushEventLog(NULL);
     }
 }
 


=====================================
rts/Trace.h
=====================================
@@ -319,7 +319,6 @@ void traceConcSweepEnd(void);
 void traceConcUpdRemSetFlush(Capability *cap);
 void traceNonmovingHeapCensus(uint32_t log_blk_size,
                               const struct NonmovingAllocCensus *census);
-
 void flushTrace(void);
 
 #else /* !TRACING */


=====================================
rts/eventlog/EventLog.c
=====================================
@@ -16,6 +16,7 @@
 #include "RtsUtils.h"
 #include "Stats.h"
 #include "EventLog.h"
+#include "Schedule.h"
 
 #include <string.h>
 #include <stdio.h>
@@ -271,7 +272,7 @@ stopEventLogWriter(void)
 }
 
 void
-flushEventLog(void)
+flushEventLogWriter(void)
 {
     if (event_log_writer != NULL &&
             event_log_writer->flushEventLog != NULL) {
@@ -1565,6 +1566,40 @@ void postEventType(EventsBuf *eb, EventType *et)
     postInt32(eb, EVENT_ET_END);
 }
 
+void flushLocalEventsBuf(Capability *cap)
+{
+    EventsBuf *eb = &capEventBuf[cap->no];
+    printAndClearEventBuf(eb);
+}
+
+// Flush all capabilities' event buffers when we already hold all capabilities.
+// Used during forkProcess.
+void flushAllCapsEventsBufs()
+{
+    ACQUIRE_LOCK(&eventBufMutex);
+    printAndClearEventBuf(&eventBuf);
+    RELEASE_LOCK(&eventBufMutex);
+
+    for (int i=0; i < n_capabilities; i++) {
+        flushLocalEventsBuf(capabilities[i]);
+    }
+    flushEventLogWriter();
+}
+
+void flushEventLog(Capability **cap USED_IF_THREADS)
+{
+    ACQUIRE_LOCK(&eventBufMutex);
+    printAndClearEventBuf(&eventBuf);
+    RELEASE_LOCK(&eventBufMutex);
+
+#if defined(THREADED_RTS)
+    Task *task = getTask();
+    stopAllCapabilitiesWith(cap, task, SYNC_FLUSH_EVENT_LOG);
+    releaseAllCapabilities(n_capabilities, cap ? *cap : NULL, task);
+#endif
+    flushEventLogWriter();
+}
+
 #else
 
 enum EventLogStatus eventLogStatus(void)
@@ -1578,4 +1613,6 @@ bool startEventLogging(const EventLogWriter *writer STG_UNUSED) {
 
 void endEventLogging(void) {}
 
+void flushEventLog(Capability **cap STG_UNUSED) {}
+
 #endif /* TRACING */


=====================================
rts/eventlog/EventLog.h
=====================================
@@ -28,8 +28,11 @@ void initEventLogging(void);
 void restartEventLogging(void);
 void freeEventLogging(void);
 void abortEventLogging(void); // #4512 - after fork child needs to abort
-void flushEventLog(void);     // event log inherited from parent
+void flushEventLogWriter(void);     // event log inherited from parent
 void moreCapEventBufs (uint32_t from, uint32_t to);
+void flushLocalEventsBuf(Capability *cap);
+void flushAllCapsEventsBufs(void);
+void flushAllEventsBufs(Capability *cap);
 
 /*
  * Post a scheduler event to the capability's event buffer (an event
@@ -175,6 +178,9 @@ void postNonmovingHeapCensus(int log_blk_size,
 
 #else /* !TRACING */
 
+INLINE_HEADER void flushLocalEventsBuf(Capability *cap)
+{ /* nothing */ }
+
 INLINE_HEADER void postSchedEvent (Capability *cap  STG_UNUSED,
                                    EventTypeNum tag STG_UNUSED,
                                    StgThreadID id   STG_UNUSED,



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/9f8e0e9c4f76f00318e3d628fcfd9e67297409d0

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/9f8e0e9c4f76f00318e3d628fcfd9e67297409d0
You're receiving this email because of your account on gitlab.haskell.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20200422/6ab5908d/attachment-0001.html>


More information about the ghc-commits mailing list