#include "Trace.h"
#include "Capability.h"
-#include "Trace.h"
#include "RtsUtils.h"
#include "Stats.h"
#include "EventLog.h"
-#include <string.h>
+#include <string.h>
#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+// PID of the process that writes to event_log_filename (#4512)
+static pid_t event_log_pid = -1;
static char *event_log_filename = NULL;
[EVENT_REQUEST_PAR_GC] = "Request parallel GC",
[EVENT_CREATE_SPARK_THREAD] = "Create spark thread",
[EVENT_LOG_MSG] = "Log message",
+ [EVENT_USER_MSG] = "User message",
[EVENT_STARTUP] = "Startup",
+ [EVENT_GC_IDLE] = "GC idle",
+ [EVENT_GC_WORK] = "GC working",
+ [EVENT_GC_DONE] = "GC done",
[EVENT_BLOCK_MARKER] = "Block marker"
};
static void postEventType(EventsBuf *eb, EventType *et);
-static void postLogMsg(EventsBuf *eb, char *msg, va_list ap);
+static void postLogMsg(EventsBuf *eb, EventTypeNum type, char *msg, va_list ap);
static void postBlockMarker(EventsBuf *eb);
static void closeBlockMarker(EventsBuf *ebuf);
StgWord8 t, c;
nat n_caps;
- event_log_filename = stgMallocBytes(strlen(prog_name) + 10,
+ event_log_filename = stgMallocBytes(strlen(prog_name)
+ + 10 /* .%d */
+ + 10 /* .eventlog */,
"initEventLogging");
if (sizeof(EventDesc) / sizeof(char*) != NUM_EVENT_TAGS) {
barf("EventDesc array has the wrong number of elements");
}
-
- sprintf(event_log_filename, "%s.eventlog", prog_name);
-
+
+ if (event_log_pid == -1) { // #4512
+ // Single process
+ sprintf(event_log_filename, "%s.eventlog", prog_name);
+ event_log_pid = getpid();
+ } else {
+ // Forked process, eventlog already started by the parent
+ // before fork
+ event_log_pid = getpid();
+ sprintf(event_log_filename, "%s.%d.eventlog", prog_name, event_log_pid);
+ }
+
/* Open event log file for writing. */
if ((event_log_file = fopen(event_log_filename, "wb")) == NULL) {
sysErrorBelch("initEventLogging: can't open %s", event_log_filename);
case EVENT_STOP_THREAD: // (cap, thread, status)
eventTypes[t].size =
- sizeof(EventThreadID) + sizeof(StgWord16);
+ sizeof(EventThreadID) + sizeof(StgWord16) + sizeof(EventThreadID);
+ break;
+
+ case EVENT_STARTUP: // (cap count)
+ eventTypes[t].size = sizeof(EventCapNo);
break;
case EVENT_SHUTDOWN: // (cap)
case EVENT_REQUEST_PAR_GC: // (cap)
case EVENT_GC_START: // (cap)
case EVENT_GC_END: // (cap)
- case EVENT_STARTUP:
+ case EVENT_GC_IDLE:
+ case EVENT_GC_WORK:
+ case EVENT_GC_DONE:
eventTypes[t].size = 0;
break;
case EVENT_LOG_MSG: // (msg)
+ case EVENT_USER_MSG: // (msg)
eventTypes[t].size = 0xffff;
break;
for (c = 0; c < n_caps; ++c) {
postBlockMarker(&capEventBuf[c]);
}
+
+#ifdef THREADED_RTS
+ initMutex(&eventBufMutex);
+#endif
}
void
}
}
+void
+flushEventLog(void)
+{
+ if (event_log_file != NULL) {
+ fflush(event_log_file);
+ }
+}
+
+void
+abortEventLogging(void)
+{
+ freeEventLogging();
+ if (event_log_file != NULL) {
+ fclose(event_log_file);
+ }
+}
/*
* Post an event message to the capability's eventlog buffer.
* If the buffer is full, prints out the buffer and clears it.
postSchedEvent (Capability *cap,
EventTypeNum tag,
StgThreadID thread,
- StgWord64 other)
+ StgWord info1,
+ StgWord info2)
{
EventsBuf *eb;
case EVENT_CREATE_SPARK_THREAD: // (cap, spark_thread)
{
- postThreadID(eb,other /* spark_thread */);
+ postThreadID(eb,info1 /* spark_thread */);
break;
}
case EVENT_THREAD_WAKEUP: // (cap, thread, other_cap)
{
postThreadID(eb,thread);
- postCapNo(eb,other /* new_cap | victim_cap | other_cap */);
+ postCapNo(eb,info1 /* new_cap | victim_cap | other_cap */);
break;
}
case EVENT_STOP_THREAD: // (cap, thread, status)
{
postThreadID(eb,thread);
- postWord16(eb,other /* status */);
+ postWord16(eb,info1 /* status */);
+ postThreadID(eb,info2 /* blocked on thread */);
break;
}
}
}
+void
+postEvent (Capability *cap, EventTypeNum tag)
+{
+ EventsBuf *eb;
+
+ eb = &capEventBuf[cap->no];
+
+ if (!hasRoomForEvent(eb, tag)) {
+ // Flush event buffer to make room for new event.
+ printAndClearEventBuf(eb);
+ }
+
+ postEventHeader(eb, tag);
+}
+
#define BUF 512
-void postLogMsg(EventsBuf *eb, char *msg, va_list ap)
+void postLogMsg(EventsBuf *eb, EventTypeNum type, char *msg, va_list ap)
{
char buf[BUF];
nat size;
printAndClearEventBuf(eb);
}
- postEventHeader(eb, EVENT_LOG_MSG);
+ postEventHeader(eb, type);
postPayloadSize(eb, size);
postBuf(eb,(StgWord8*)buf,size);
}
void postMsg(char *msg, va_list ap)
{
ACQUIRE_LOCK(&eventBufMutex);
- postLogMsg(&eventBuf, msg, ap);
+ postLogMsg(&eventBuf, EVENT_LOG_MSG, msg, ap);
RELEASE_LOCK(&eventBufMutex);
}
void postCapMsg(Capability *cap, char *msg, va_list ap)
{
- postLogMsg(&capEventBuf[cap->no], msg, ap);
+ postLogMsg(&capEventBuf[cap->no], EVENT_LOG_MSG, msg, ap);
}
+void postUserMsg(Capability *cap, char *msg, va_list ap)
+{
+ postLogMsg(&capEventBuf[cap->no], EVENT_USER_MSG, msg, ap);
+}
+
void closeBlockMarker (EventsBuf *ebuf)
{
StgInt8* save_pos;