From 58532eb46041aec8d4cbb48b054cb5b001edb43c Mon Sep 17 00:00:00 2001 From: Spencer Janssen Date: Thu, 14 Apr 2011 01:11:05 -0500 Subject: [PATCH] Add capability sets to the event system. Contains code from Duncan Coutts. --- includes/rts/EventLogFormat.h | 39 ++++++++++- rts/Capability.c | 4 ++ rts/RtsProbes.d | 6 ++ rts/RtsStartup.c | 4 ++ rts/Schedule.c | 16 ++--- rts/Trace.c | 67 ++++++++++++++++++ rts/Trace.h | 69 +++++++++++++++++++ rts/eventlog/EventLog.c | 149 ++++++++++++++++++++++++++++++++++++++++- rts/eventlog/EventLog.h | 29 ++++++++ rts/ghc.mk | 1 + 10 files changed, 374 insertions(+), 10 deletions(-) diff --git a/includes/rts/EventLogFormat.h b/includes/rts/EventLogFormat.h index f3f56c9..16f1c8b 100644 --- a/includes/rts/EventLogFormat.h +++ b/includes/rts/EventLogFormat.h @@ -112,6 +112,7 @@ #define EVENT_GC_END 10 /* () */ #define EVENT_REQUEST_SEQ_GC 11 /* () */ #define EVENT_REQUEST_PAR_GC 12 /* () */ +/* 13, 14 deprecated */ #define EVENT_CREATE_SPARK_THREAD 15 /* (spark_thread) */ #define EVENT_LOG_MSG 16 /* (message ...) */ #define EVENT_STARTUP 17 /* (num_capabilities) */ @@ -120,12 +121,39 @@ #define EVENT_GC_IDLE 20 /* () */ #define EVENT_GC_WORK 21 /* () */ #define EVENT_GC_DONE 22 /* () */ +/* 23, 24 used by eden */ +#define EVENT_CAPSET_CREATE 25 /* (capset, capset_type) */ +#define EVENT_CAPSET_DELETE 26 /* (capset) */ +#define EVENT_CAPSET_ASSIGN_CAP 27 /* (capset, cap) */ +#define EVENT_CAPSET_REMOVE_CAP 28 /* (capset, cap) */ +/* the RTS identifier is in the form of "GHC-version rts_way" */ +#define EVENT_RTS_IDENTIFIER 29 /* (capset, name_version_string) */ +/* the vectors in these events are null separated strings */ +#define EVENT_PROGRAM_ARGS 30 /* (capset, commandline_vector) */ +#define EVENT_PROGRAM_ENV 31 /* (capset, environment_vector) */ +#define EVENT_OSPROCESS_PID 32 /* (capset, pid, parent_pid) */ -#define NUM_EVENT_TAGS 23 + +/* Range 33 - 59 is available for new events */ + +/* Range 60 - 80 is used by eden for parallel tracing + * see http://www.mathematik.uni-marburg.de/~eden/ + */ + +/* + * The highest event code +1 that ghc itself emits. Note that some event + * ranges higher than this are reserved but not currently emitted by ghc. + * This must match the size of the EventDesc[] array in EventLog.c + */ +#define NUM_EVENT_TAGS 33 #if 0 /* DEPRECATED EVENTS: */ +/* ghc changed how it handles sparks so these are no longer applicable */ #define EVENT_CREATE_SPARK 13 /* (cap, thread) */ #define EVENT_SPARK_TO_THREAD 14 /* (cap, thread, spark_thread) */ +/* these are used by eden but are replaced by new alternatives for ghc */ +#define EVENT_VERSION 23 /* (version_string) */ +#define EVENT_PROGRAM_INVOCATION 24 /* (commandline_string) */ #endif /* @@ -152,6 +180,13 @@ */ #define THREAD_SUSPENDED_FOREIGN_CALL 6 +/* + * Capset type values for EVENT_CAPSET_CREATE + */ +#define CAPSET_TYPE_CUSTOM 1 /* reserved for end-user applications */ +#define CAPSET_TYPE_OSPROCESS 2 /* caps belong to the same OS process */ +#define CAPSET_TYPE_CLOCKDOMAIN 3 /* caps share a local clock/time */ + #ifndef EVENTLOG_CONSTANTS_ONLY typedef StgWord16 EventTypeNum; @@ -160,6 +195,8 @@ typedef StgWord32 EventThreadID; typedef StgWord16 EventCapNo; typedef StgWord16 EventPayloadSize; /* variable-size events */ typedef StgWord16 EventThreadStatus; /* status for EVENT_STOP_THREAD */ +typedef StgWord32 EventCapsetID; +typedef StgWord16 EventCapsetType; /* types for EVENT_CAPSET_CREATE */ #endif diff --git a/rts/Capability.c b/rts/Capability.c index 9091fdd..9557fcc 100644 --- a/rts/Capability.c +++ b/rts/Capability.c @@ -253,6 +253,8 @@ initCapability( Capability *cap, nat i ) cap->transaction_tokens = 0; cap->context_switch = 0; cap->pinned_object_block = NULL; + + traceCapsetAssignCap(CAPSET_OSPROCESS_DEFAULT, i); } /* --------------------------------------------------------------------------- @@ -266,6 +268,7 @@ initCapability( Capability *cap, nat i ) void initCapabilities( void ) { + #if defined(THREADED_RTS) nat i; @@ -833,6 +836,7 @@ freeCapabilities (void) #else freeCapability(&MainCapability); #endif + traceCapsetDelete(CAPSET_OSPROCESS_DEFAULT); } /* --------------------------------------------------------------------------- diff --git a/rts/RtsProbes.d b/rts/RtsProbes.d index dbc5111..bd32fca 100644 --- a/rts/RtsProbes.d +++ b/rts/RtsProbes.d @@ -23,6 +23,8 @@ * typedef uint16_t EventCapNo; * typedef uint16_t EventPayloadSize; // variable-size events * typedef uint16_t EventThreadStatus; + * typedef uint32_t EventCapsetID; + * typedef uint16_t EventCapsetType; // types for EVENT_CAPSET_CREATE */ /* ----------------------------------------------------------------------------- @@ -60,5 +62,9 @@ provider HaskellEvent { probe gc__idle (EventCapNo); probe gc__work (EventCapNo); probe gc__done (EventCapNo); + probe capset__create(EventCapsetID, EventCapsetType); + probe capset__delete(EventCapsetID); + probe capset__assign__cap(EventCapsetID, EventCapNo); + probe capset__remove__cap(EventCapsetID, EventCapNo); }; diff --git a/rts/RtsStartup.c b/rts/RtsStartup.c index 236d07a..502906e 100644 --- a/rts/RtsStartup.c +++ b/rts/RtsStartup.c @@ -148,6 +148,10 @@ hs_init(int *argc, char **argv[]) */ dtraceEventStartup(); + /* Trace some basic information about the process + */ + traceCapsetDetails(argc, argv); + /* initialise scheduler data structures (needs to be done before * initStorage()). */ diff --git a/rts/Schedule.c b/rts/Schedule.c index 9636223..9b151d7 100644 --- a/rts/Schedule.c +++ b/rts/Schedule.c @@ -2030,16 +2030,16 @@ exitScheduler (rtsBool wait_foreign USED_IF_THREADS) } sched_state = SCHED_SHUTTING_DOWN; + nat i; + + for (i = 0; i < n_capabilities; i++) { #if defined(THREADED_RTS) - { - nat i; - - for (i = 0; i < n_capabilities; i++) { - ASSERT(task->incall->tso == NULL); - shutdownCapability(&capabilities[i], task, wait_foreign); - } - } + ASSERT(task->incall->tso == NULL); + shutdownCapability(&capabilities[i], task, wait_foreign); #endif + traceCapsetRemoveCap(CAPSET_OSPROCESS_DEFAULT, i); + } + traceCapsetDelete(CAPSET_OSPROCESS_DEFAULT); boundTaskExiting(task); } diff --git a/rts/Trace.c b/rts/Trace.c index f2f9e81..fb8e922 100644 --- a/rts/Trace.c +++ b/rts/Trace.c @@ -20,6 +20,10 @@ #include "Threads.h" #include "Printer.h" +#ifdef HAVE_UNISTD_H +#include +#endif + #ifdef DEBUG // debugging flags, set with +RTS -D int DEBUG_sched; @@ -251,6 +255,69 @@ void traceSchedEvent_ (Capability *cap, EventTypeNum tag, } } +void traceCapsetModify_ (EventTypeNum tag, + CapsetID capset, + StgWord32 other, + StgWord32 other2) +{ +#ifdef DEBUG + if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) { + ACQUIRE_LOCK(&trace_utx); + + tracePreface(); + switch (tag) { + case EVENT_CAPSET_CREATE: // (capset, capset_type) + debugBelch("created capset %d of type %d\n", capset, other); + break; + case EVENT_CAPSET_DELETE: // (capset) + debugBelch("deleted capset %d\n", capset); + break; + case EVENT_CAPSET_ASSIGN_CAP: // (capset, capno) + debugBelch("assigned cap %d to capset %d\n", other, capset); + break; + case EVENT_CAPSET_REMOVE_CAP: // (capset, capno) + debugBelch("removed cap %d from capset %d\n", other, capset); + break; + } + RELEASE_LOCK(&trace_utx); + } else +#endif + { + if(eventlog_enabled) postCapsetModifyEvent(tag, capset, other, other2); + } +} + +extern char **environ; + +void traceCapsetDetails_(int *argc, char **argv[]){ + if(eventlog_enabled){ + postCapsetModifyEvent(EVENT_OSPROCESS_PID, + CAPSET_OSPROCESS_DEFAULT, + getpid(), + getppid()); + + char buf[256]; + snprintf(buf, sizeof(buf), "GHC-%s %s", ProjectVersion, RtsWay); + postCapsetStrEvent(EVENT_RTS_IDENTIFIER, + CAPSET_OSPROCESS_DEFAULT, + buf); + + if(argc != NULL && argv != NULL){ + postCapsetVecEvent(EVENT_PROGRAM_ARGS, + CAPSET_OSPROCESS_DEFAULT, + *argc, + *argv); + } + + int env_len; + for( env_len = 0; environ[env_len] != NULL; env_len++); + postCapsetVecEvent(EVENT_PROGRAM_ENV, + CAPSET_OSPROCESS_DEFAULT, + env_len, + environ); + } +} + void traceEvent_ (Capability *cap, EventTypeNum tag) { #ifdef DEBUG diff --git a/rts/Trace.h b/rts/Trace.h index 6209156..04075ad 100644 --- a/rts/Trace.h +++ b/rts/Trace.h @@ -31,6 +31,13 @@ void resetTracing (void); #endif /* TRACING */ +typedef StgWord32 CapsetID; +typedef StgWord16 CapsetType; +enum CapsetType { CapsetTypeCustom = CAPSET_TYPE_CUSTOM, + CapsetTypeOsProcess = CAPSET_TYPE_OSPROCESS, + CapsetTypeClockdomain = CAPSET_TYPE_CLOCKDOMAIN }; +#define CAPSET_OSPROCESS_DEFAULT 0 + // ----------------------------------------------------------------------------- // Message classes // ----------------------------------------------------------------------------- @@ -160,6 +167,21 @@ void traceUserMsg(Capability *cap, char *msg); void traceThreadStatus_ (StgTSO *tso); +/* + * Events for describing capability sets in the eventlog + * + * Note: unlike other events, these are not conditional on TRACE_sched or + * similar because they are not "real" events themselves but provide + * information and context for other "real" events. Other events depend on + * the capset info events so for simplicity, rather than working out if + * they're necessary we always emit them. They should be very low volume. + */ +void traceCapsetModify_ (EventTypeNum tag, + CapsetID capset, + StgWord32 other, + StgWord32 other2); + +void traceCapsetDetails_ (int *argc, char **argv[]); #else /* !TRACING */ #define traceSchedEvent(cap, tag, tso, other) /* nothing */ @@ -170,6 +192,8 @@ void traceThreadStatus_ (StgTSO *tso); #define debugTrace(class, str, ...) /* nothing */ #define debugTraceCap(class, cap, str, ...) /* nothing */ #define traceThreadStatus(class, tso) /* nothing */ +#define traceCapsetModify_(tag, capset, other, other2) /* nothing */ +#define traceCapsetDetails_(argc, argv) /* nothing */ #endif /* TRACING */ @@ -226,6 +250,14 @@ void dtraceUserMsgWrapper(Capability *cap, char *msg); HASKELLEVENT_GC_WORK(cap) #define dtraceGcDone(cap) \ HASKELLEVENT_GC_DONE(cap) +#define dtraceCapsetCreate(capset, capset_type) \ + HASKELLEVENT_CAPSET_CREATE(capset, capset_type) +#define dtraceCapsetDelete(capset) \ + HASKELLEVENT_CAPSET_DELETE(capset) +#define dtraceCapsetAssignCap(capset, capno) \ + HASKELLEVENT_CAPSET_ASSIGN_CAP(capset, capno) +#define dtraceCapsetRemoveCap(capset, capno) \ + HASKELLEVENT_CAPSET_REMOVE_CAP(capset, capno) #else /* !defined(DTRACE) */ @@ -248,6 +280,10 @@ void dtraceUserMsgWrapper(Capability *cap, char *msg); #define dtraceGcIdle(cap) /* nothing */ #define dtraceGcWork(cap) /* nothing */ #define dtraceGcDone(cap) /* nothing */ +#define dtraceCapsetCreate(capset, capset_type) /* nothing */ +#define dtraceCapsetDelete(capset) /* nothing */ +#define dtraceCapsetAssignCap(capset, capno) /* nothing */ +#define dtraceCapsetRemoveCap(capset, capno) /* nothing */ #endif @@ -405,6 +441,39 @@ INLINE_HEADER void traceEventGcDone(Capability *cap STG_UNUSED) dtraceGcDone((EventCapNo)cap->no); } +INLINE_HEADER void traceCapsetCreate(CapsetID capset STG_UNUSED, + CapsetType capset_type STG_UNUSED) +{ + traceCapsetModify_(EVENT_CAPSET_CREATE, capset, capset_type, 0); + dtraceCapsetCreate(capset, capset_type); +} + +INLINE_HEADER void traceCapsetDelete(CapsetID capset STG_UNUSED) +{ + traceCapsetModify_(EVENT_CAPSET_DELETE, capset, 0, 0); + dtraceCapsetDelete(capset); +} + +INLINE_HEADER void traceCapsetAssignCap(CapsetID capset STG_UNUSED, + nat capno STG_UNUSED) +{ + traceCapsetModify_(EVENT_CAPSET_ASSIGN_CAP, capset, capno, 0); + dtraceCapsetAssignCap(capset, capno); +} + +INLINE_HEADER void traceCapsetRemoveCap(CapsetID capset STG_UNUSED, + nat capno STG_UNUSED) +{ + traceCapsetModify_(EVENT_CAPSET_REMOVE_CAP, capset, capno, 0); + dtraceCapsetRemoveCap(capset, capno); +} + +INLINE_HEADER void traceCapsetDetails(int *argc STG_UNUSED, char **argv[] STG_UNUSED) +{ + traceCapsetCreate(CAPSET_OSPROCESS_DEFAULT, CapsetTypeOsProcess); + traceCapsetDetails_(argc, argv); +} + #include "EndPrivate.h" #endif /* TRACE_H */ diff --git a/rts/eventlog/EventLog.c b/rts/eventlog/EventLog.c index a77c257..d2e3de3 100644 --- a/rts/eventlog/EventLog.c +++ b/rts/eventlog/EventLog.c @@ -75,7 +75,15 @@ char *EventDesc[] = { [EVENT_GC_IDLE] = "GC idle", [EVENT_GC_WORK] = "GC working", [EVENT_GC_DONE] = "GC done", - [EVENT_BLOCK_MARKER] = "Block marker" + [EVENT_BLOCK_MARKER] = "Block marker", + [EVENT_CAPSET_CREATE] = "Create capability set", + [EVENT_CAPSET_DELETE] = "Delete capability set", + [EVENT_CAPSET_ASSIGN_CAP] = "Add capability to capability set", + [EVENT_CAPSET_REMOVE_CAP] = "Remove capability from capability set", + [EVENT_RTS_IDENTIFIER] = "Identify the RTS version", + [EVENT_PROGRAM_ARGS] = "Identify the program arguments", + [EVENT_PROGRAM_ENV] = "Identify the environment variables", + [EVENT_OSPROCESS_PID] = "Identify the process ID of a capability set" }; // Event type. @@ -146,6 +154,12 @@ static inline void postThreadID(EventsBuf *eb, EventThreadID id) static inline void postCapNo(EventsBuf *eb, EventCapNo no) { postWord16(eb,no); } +static inline void postCapsetID(EventsBuf *eb, EventCapsetID id) +{ postWord32(eb,id); } + +static inline void postCapsetType(EventsBuf *eb, EventCapsetType type) +{ postWord16(eb,type); } + static inline void postPayloadSize(EventsBuf *eb, EventPayloadSize size) { postWord16(eb,size); } @@ -259,6 +273,26 @@ initEventLogging(void) eventTypes[t].size = sizeof(EventCapNo); break; + case EVENT_CAPSET_CREATE: // (capset, capset_type) + eventTypes[t].size = + sizeof(EventCapsetID) + sizeof(EventCapsetType); + break; + + case EVENT_CAPSET_DELETE: // (capset) + eventTypes[t].size = sizeof(EventCapsetID); + break; + + case EVENT_CAPSET_ASSIGN_CAP: // (capset, cap) + case EVENT_CAPSET_REMOVE_CAP: + eventTypes[t].size = + sizeof(EventCapsetID) + sizeof(EventCapNo); + break; + + case EVENT_OSPROCESS_PID: // (cap, pid, parent pid) + eventTypes[t].size = + sizeof(EventCapsetID) + 2*sizeof(StgWord32); + break; + case EVENT_SHUTDOWN: // (cap) case EVENT_REQUEST_SEQ_GC: // (cap) case EVENT_REQUEST_PAR_GC: // (cap) @@ -272,6 +306,9 @@ initEventLogging(void) case EVENT_LOG_MSG: // (msg) case EVENT_USER_MSG: // (msg) + case EVENT_RTS_IDENTIFIER: // (capset, str) + case EVENT_PROGRAM_ARGS: // (capset, strvec) + case EVENT_PROGRAM_ENV: // (capset, strvec) eventTypes[t].size = 0xffff; break; @@ -443,6 +480,116 @@ postSchedEvent (Capability *cap, } } +void postCapsetModifyEvent (EventTypeNum tag, + EventCapsetID capset, + StgWord32 other, + StgWord32 other2) +{ + ACQUIRE_LOCK(&eventBufMutex); + + if (!hasRoomForEvent(&eventBuf, tag)) { + // Flush event buffer to make room for new event. + printAndClearEventBuf(&eventBuf); + } + + postEventHeader(&eventBuf, tag); + postCapsetID(&eventBuf, capset); + + switch (tag) { + case EVENT_CAPSET_CREATE: // (capset, capset_type) + { + postCapsetType(&eventBuf, other /* capset_type */); + break; + } + + case EVENT_CAPSET_DELETE: // (capset) + { + break; + } + + case EVENT_CAPSET_ASSIGN_CAP: // (capset, capno) + case EVENT_CAPSET_REMOVE_CAP: // (capset, capno) + { + postCapNo(&eventBuf, other /* capno */); + break; + } + case EVENT_OSPROCESS_PID: + { + postWord32(&eventBuf, other); + postWord32(&eventBuf, other2); + break; + } + default: + barf("postCapsetModifyEvent: unknown event tag %d", tag); + } + + RELEASE_LOCK(&eventBufMutex); +} + +void postCapsetStrEvent (EventTypeNum tag, + EventCapsetID capset, + char *msg) +{ + int strsize = strlen(msg); + int size = strsize + sizeof(EventCapsetID) + + ACQUIRE_LOCK(&eventBufMutex); + + if (!hasRoomForVariableEvent(&eventBuf, size)){ + printAndClearEventBuf(&eventBuf); + + if (!hasRoomForVariableEvent(&eventBuf, size)){ + // Event size exceeds buffer size, bail out: + RELEASE_LOCK(&eventBufMutex); + return; + } + } + + postEventHeader(&eventBuf, tag); + postPayloadSize(&eventBuf, size); + postCapsetID(&eventBuf, capset); + + postBuf(&eventBuf, (StgWord8*) msg, strsize); + + RELEASE_LOCK(&eventBufMutex); +} + +void postCapsetVecEvent (EventTypeNum tag, + EventCapsetID capset, + int argc, + char *argv[]) +{ + int i, size = sizeof(EventCapsetID); + + for (i = 0; i < argc; i++) { + // 1 + strlen to account for the trailing \0, used as separator + size += 1 + strlen(argv[i]); + } + + ACQUIRE_LOCK(&eventBufMutex); + + if (!hasRoomForVariableEvent(&eventBuf, size)){ + printAndClearEventBuf(&eventBuf); + + if(!hasRoomForVariableEvent(&eventBuf, size)){ + // Event size exceeds buffer size, bail out: + RELEASE_LOCK(&eventBufMutex); + return; + } + } + + postEventHeader(&eventBuf, tag); + postPayloadSize(&eventBuf, size); + postCapsetID(&eventBuf, capset); + + for( i = 0; i < argc; i++ ) { + // again, 1 + to account for \0 + postBuf(&eventBuf, (StgWord8*) argv[i], 1 + strlen(argv[i])); + } + + RELEASE_LOCK(&eventBufMutex); +} + void postEvent (Capability *cap, EventTypeNum tag) { diff --git a/rts/eventlog/EventLog.h b/rts/eventlog/EventLog.h index 0cfab5c..26a2e94 100644 --- a/rts/eventlog/EventLog.h +++ b/rts/eventlog/EventLog.h @@ -35,6 +35,29 @@ void postSchedEvent(Capability *cap, EventTypeNum tag, StgThreadID id, StgWord info1, StgWord info2); /* + * Post a capability set modification event + */ +void postCapsetModifyEvent (EventTypeNum tag, + EventCapsetID capset, + StgWord32 other, + StgWord32 other2); + +/* + * Post a capability set event with a string payload + */ +void postCapsetStrEvent (EventTypeNum tag, + EventCapsetID capset, + char *msg); + +/* + * Post a capability set event with several strings payload + */ +void postCapsetVecEvent (EventTypeNum tag, + EventCapsetID capset, + int argc, + char *msg[]); + +/* * Post a nullary event. */ void postEvent(Capability *cap, EventTypeNum tag); @@ -54,6 +77,12 @@ INLINE_HEADER void postSchedEvent (Capability *cap STG_UNUSED, StgWord info2 STG_UNUSED) { /* nothing */ } +INLINE_HEADER void postCapsetModifyEvent (EventTypeNum tag STG_UNUSED, + EventCapsetID capset STG_UNUSED, + StgWord32 other STG_UNUSED, + StgWord32 other2 STG_UNUSED) +{ /* nothing */ } + INLINE_HEADER void postEvent (Capability *cap STG_UNUSED, EventTypeNum tag STG_UNUSED) { /* nothing */ } diff --git a/rts/ghc.mk b/rts/ghc.mk index a236945..38ddbc0 100644 --- a/rts/ghc.mk +++ b/rts/ghc.mk @@ -295,6 +295,7 @@ rts/RtsMain_HC_OPTS += -optc-O0 rts/RtsMessages_CC_OPTS += -DProjectVersion=\"$(ProjectVersion)\" rts/RtsUtils_CC_OPTS += -DProjectVersion=\"$(ProjectVersion)\" +rts/Trace_CC_OPTS += -DProjectVersion=\"$(ProjectVersion)\" # rts/RtsUtils_CC_OPTS += -DHostPlatform=\"$(HOSTPLATFORM)\" rts/RtsUtils_CC_OPTS += -DHostArch=\"$(HostArch_CPP)\" -- 1.7.10.4