[Git][ghc/ghc][wip/T18043] rts: Flush eventlog buffers from flushEventLog
Ben Gamari
gitlab at gitlab.haskell.org
Thu Apr 23 13:57:56 UTC 2020
Ben Gamari pushed to branch wip/T18043 at Glasgow Haskell Compiler / GHC
Commits:
b643e4f9 by Ben Gamari at 2020-04-23T09:57:42-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 STG_UNUSED)
+{ /* 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/b643e4f9dd7b6a4731816598fb9457b1bef8914d
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/b643e4f9dd7b6a4731816598fb9457b1bef8914d
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/20200423/b64c4935/attachment-0001.html>
More information about the ghc-commits
mailing list