diff options
author | Matthew Pickering <matthewtpickering@gmail.com> | 2021-03-05 11:20:39 +0000 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2021-03-08 18:25:19 -0500 |
commit | bfa862503a9f8b2e8a61b9499d2cc3be789779fd (patch) | |
tree | 1d56c9d0165c49a65f33d62f66543b4d5163b7e2 /rts/eventlog | |
parent | 47d6acd3be1fadc0c59b7b4d4e105242c0ae0b90 (diff) | |
download | haskell-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.c | 66 | ||||
-rw-r--r-- | rts/eventlog/EventLog.h | 23 |
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 */ } |