summaryrefslogtreecommitdiff
path: root/rts/eventlog
diff options
context:
space:
mode:
authorMatthew Pickering <matthewtpickering@gmail.com>2021-03-05 11:20:39 +0000
committerMarge Bot <ben+marge-bot@smart-cactus.org>2021-03-08 18:25:19 -0500
commitbfa862503a9f8b2e8a61b9499d2cc3be789779fd (patch)
tree1d56c9d0165c49a65f33d62f66543b4d5163b7e2 /rts/eventlog
parent47d6acd3be1fadc0c59b7b4d4e105242c0ae0b90 (diff)
downloadhaskell-bfa862503a9f8b2e8a61b9499d2cc3be789779fd.tar.gz
eventlog: Repost initialisation events when eventlog restarts
If startEventlog is called after the program has already started running then quite a few useful events are missing from the eventlog because they are only posted when the program starts. This patch adds a mechanism to declare that an event should be reposted everytime the startEventlog function is called. Now in EventLog.c there is a global list of functions called `eventlog_header_funcs` which stores a list of functions which should be called everytime the eventlog starts. When calling `postInitEvent`, the event will not only be immediately posted to the eventlog but also added to the global list. When startEventLog is called, the list is traversed and the events reposted.
Diffstat (limited to 'rts/eventlog')
-rw-r--r--rts/eventlog/EventLog.c66
-rw-r--r--rts/eventlog/EventLog.h23
2 files changed, 85 insertions, 4 deletions
diff --git a/rts/eventlog/EventLog.c b/rts/eventlog/EventLog.c
index ebb44a7c9e..b8a80a0d4d 100644
--- a/rts/eventlog/EventLog.c
+++ b/rts/eventlog/EventLog.c
@@ -89,6 +89,10 @@ bool eventlog_enabled; // protected by state_change_mutex to ensure
static const EventLogWriter *event_log_writer = NULL;
+// List of initialisation functions which are called each time the
+// eventlog is restarted
+static eventlog_init_func_t *eventlog_header_funcs = NULL;
+
#define EVENT_LOG_SIZE 2 * (1024 * 1024) // 2MB
static int flushCount;
@@ -213,6 +217,8 @@ static void closeBlockMarker(EventsBuf *ebuf);
static StgBool hasRoomForEvent(EventsBuf *eb, EventTypeNum eNum);
static StgBool hasRoomForVariableEvent(EventsBuf *eb, uint32_t payload_bytes);
+static void freeEventLoggingBuffer(void);
+
static void ensureRoomForEvent(EventsBuf *eb, EventTypeNum tag);
static int ensureRoomForVariableEvent(EventsBuf *eb, StgWord16 size);
@@ -610,6 +616,50 @@ postHeaderEvents(void)
postInt32(&eventBuf, EVENT_DATA_BEGIN);
}
+// These events will be reposted everytime we restart the eventlog
+void
+postInitEvent(EventlogInitPost post_init){
+ ACQUIRE_LOCK(&state_change_mutex);
+
+ // Add the event to the global list of events that will be rerun when
+ // the eventlog is restarted.
+ eventlog_init_func_t * new_func;
+ new_func = stgMallocBytes(sizeof(eventlog_init_func_t),"eventlog_init_func");
+ new_func->init_func = post_init;
+ new_func->next = eventlog_header_funcs;
+ eventlog_header_funcs = new_func;
+
+ RELEASE_LOCK(&state_change_mutex);
+ // Actually post it
+ (*post_init)();
+ return;
+}
+
+// Post events again which happened at the start of the eventlog, added by
+// postInitEvent.
+static void repostInitEvents(void){
+ eventlog_init_func_t * current_event = eventlog_header_funcs;
+ for (; current_event != NULL; current_event = current_event->next) {
+ (*(current_event->init_func))();
+ }
+ return;
+}
+
+// Clear the eventlog_header_funcs list and free the memory
+void resetInitEvents(void){
+ eventlog_init_func_t * tmp;
+ eventlog_init_func_t * current_event = eventlog_header_funcs;
+ for (; current_event != NULL; ) {
+ tmp = current_event;
+ current_event = current_event->next;
+ stgFree(tmp);
+ }
+ eventlog_header_funcs = NULL;
+ return;
+
+}
+
+
static uint32_t
get_n_capabilities(void)
{
@@ -697,6 +747,7 @@ startEventLogging(const EventLogWriter *ev_writer)
event_log_writer = ev_writer;
bool ret = startEventLogging_();
eventlog_enabled = true;
+ repostInitEvents();
RELEASE_LOCK(&state_change_mutex);
return ret;
}
@@ -705,11 +756,12 @@ startEventLogging(const EventLogWriter *ev_writer)
void
restartEventLogging(void)
{
- freeEventLogging();
+ freeEventLoggingBuffer();
stopEventLogWriter();
initEventLogging(); // allocate new per-capability buffers
if (event_log_writer != NULL) {
startEventLogging_(); // child starts its own eventlog
+ repostInitEvents(); // Repost the initialisation events
}
}
@@ -790,15 +842,21 @@ moreCapEventBufs (uint32_t from, uint32_t to)
}
}
-
-void
-freeEventLogging(void)
+static void
+freeEventLoggingBuffer(void)
{
if (capEventBuf != NULL) {
stgFree(capEventBuf);
}
}
+void
+freeEventLogging(void)
+{
+ freeEventLoggingBuffer();
+ resetInitEvents();
+}
+
/*
* Post an event message to the capability's eventlog buffer.
* If the buffer is full, prints out the buffer and clears it.
diff --git a/rts/eventlog/EventLog.h b/rts/eventlog/EventLog.h
index 9d3795f3ff..9c1201928b 100644
--- a/rts/eventlog/EventLog.h
+++ b/rts/eventlog/EventLog.h
@@ -34,6 +34,22 @@ void flushLocalEventsBuf(Capability *cap);
void flushAllCapsEventsBufs(void);
void flushAllEventsBufs(Capability *cap);
+typedef void (*EventlogInitPost)(void);
+
+// Events which are emitted during program start-up should be wrapped with
+// postInitEvent so that when the eventlog is restarted (possibly by an external
+// writer) then these events appear again at the start of the log.
+void postInitEvent(EventlogInitPost post_init);
+
+// Clear the init events buffer on program exit
+void resetInitEvents(void);
+
+typedef struct eventlog_init_func {
+ EventlogInitPost init_func;
+ struct eventlog_init_func * next;
+} eventlog_init_func_t;
+
+
/*
* Post a scheduler event to the capability's event buffer (an event
* that has an associated thread).
@@ -214,6 +230,13 @@ INLINE_HEADER void postEvent (Capability *cap STG_UNUSED,
EventTypeNum tag STG_UNUSED)
{ /* nothing */ }
+typedef void (*EventlogInitPost)(void);
+
+INLINE_HEADER void postInitEvent(EventlogInitPost f STG_UNUSED)
+{ /* nothing */ } ;
+
+
+
INLINE_HEADER void postEventNoCap (EventTypeNum tag STG_UNUSED)
{ /* nothing */ }