Enable DTrace on Solaris; based on a patch from Karel Gardas
[ghc-hetmet.git] / rts / eventlog / EventLog.c
index e5e71e6..a77c257 100644 (file)
 
 #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;
 
@@ -62,7 +70,11 @@ char *EventDesc[] = {
   [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"
 };
 
@@ -82,7 +94,7 @@ static void printAndClearEventBuf (EventsBuf *eventsBuf);
 
 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);
@@ -162,15 +174,26 @@ initEventLogging(void)
     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);
@@ -229,7 +252,11 @@ initEventLogging(void)
 
         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)
@@ -237,11 +264,14 @@ initEventLogging(void)
         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;
 
@@ -281,6 +311,10 @@ initEventLogging(void)
     for (c = 0; c < n_caps; ++c) {
         postBlockMarker(&capEventBuf[c]);
     }
+
+#ifdef THREADED_RTS
+    initMutex(&eventBufMutex);
+#endif
 }
 
 void
@@ -324,6 +358,22 @@ freeEventLogging(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.
@@ -332,7 +382,8 @@ void
 postSchedEvent (Capability *cap, 
                 EventTypeNum tag, 
                 StgThreadID thread, 
-                StgWord64 other)
+                StgWord info1,
+                StgWord info2)
 {
     EventsBuf *eb;
 
@@ -357,7 +408,7 @@ postSchedEvent (Capability *cap,
 
     case EVENT_CREATE_SPARK_THREAD: // (cap, spark_thread)
     {
-        postThreadID(eb,other /* spark_thread */);
+        postThreadID(eb,info1 /* spark_thread */);
         break;
     }
 
@@ -366,14 +417,15 @@ postSchedEvent (Capability *cap,
     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;
     }
 
@@ -391,9 +443,24 @@ postSchedEvent (Capability *cap,
     }
 }
 
+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;
@@ -409,7 +476,7 @@ void postLogMsg(EventsBuf *eb, char *msg, va_list ap)
         printAndClearEventBuf(eb);
     }
 
-    postEventHeader(eb, EVENT_LOG_MSG);
+    postEventHeader(eb, type);
     postPayloadSize(eb, size);
     postBuf(eb,(StgWord8*)buf,size);
 }
@@ -417,15 +484,20 @@ void postLogMsg(EventsBuf *eb, char *msg, va_list ap)
 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;