Commit 58532eb4 authored by Spencer Janssen's avatar Spencer Janssen Committed by Simon Marlow

Add capability sets to the event system. Contains code from Duncan Coutts.

parent 58339b06
......@@ -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
......
......@@ -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);
}
/* ---------------------------------------------------------------------------
......
......@@ -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);
};
......@@ -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()).
*/
......
......@@ -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);
}
......
......@@ -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
......
......@@ -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 */
......@@ -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)
{
......
......@@ -34,6 +34,29 @@ void flushEventLog(void); // event log inherited from parent
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.
*/
......@@ -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 */ }
......
......@@ -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)\"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment