summaryrefslogtreecommitdiff
path: root/rts
diff options
context:
space:
mode:
authorSpencer Janssen <spencer@well-typed.com>2011-04-14 01:11:05 -0500
committerSimon Marlow <marlowsd@gmail.com>2011-05-18 11:14:27 +0100
commit58532eb46041aec8d4cbb48b054cb5b001edb43c (patch)
tree1fd878273e11b04045e48178acc8eaacd2ccace9 /rts
parent58339b06aff704834e8553faaa2db00d746b26f3 (diff)
downloadhaskell-58532eb46041aec8d4cbb48b054cb5b001edb43c.tar.gz
Add capability sets to the event system. Contains code from Duncan Coutts.
Diffstat (limited to 'rts')
-rw-r--r--rts/Capability.c4
-rw-r--r--rts/RtsProbes.d6
-rw-r--r--rts/RtsStartup.c4
-rw-r--r--rts/Schedule.c16
-rw-r--r--rts/Trace.c67
-rw-r--r--rts/Trace.h69
-rw-r--r--rts/eventlog/EventLog.c149
-rw-r--r--rts/eventlog/EventLog.h29
-rw-r--r--rts/ghc.mk1
9 files changed, 336 insertions, 9 deletions
diff --git a/rts/Capability.c b/rts/Capability.c
index 9091fdde0c..9557fcc07f 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 dbc5111e46..bd32fca385 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 236d07a9e0..502906ebed 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 9636223836..9b151d7283 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 f2f9e81549..fb8e9226af 100644
--- a/rts/Trace.c
+++ b/rts/Trace.c
@@ -20,6 +20,10 @@
#include "Threads.h"
#include "Printer.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
#ifdef DEBUG
// debugging flags, set with +RTS -D<something>
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 620915665b..04075ad6e9 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 a77c257e1b..d2e3de35ff 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 0cfab5c091..26a2e944bf 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 a2369452b7..38ddbc0d46 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)\"