diff options
-rw-r--r-- | compiler/prelude/primops.txt.pp | 11 | ||||
-rw-r--r-- | includes/rts/EventLogFormat.h | 6 | ||||
-rw-r--r-- | includes/stg/MiscClosures.h | 1 | ||||
-rw-r--r-- | rts/Linker.c | 1 | ||||
-rw-r--r-- | rts/PrimOps.cmm | 25 | ||||
-rw-r--r-- | rts/RtsProbes.d | 1 | ||||
-rw-r--r-- | rts/Trace.c | 22 | ||||
-rw-r--r-- | rts/Trace.h | 10 | ||||
-rw-r--r-- | rts/eventlog/EventLog.c | 23 | ||||
-rw-r--r-- | rts/eventlog/EventLog.h | 2 |
10 files changed, 99 insertions, 3 deletions
diff --git a/compiler/prelude/primops.txt.pp b/compiler/prelude/primops.txt.pp index 2e56e981a5..7730106c46 100644 --- a/compiler/prelude/primops.txt.pp +++ b/compiler/prelude/primops.txt.pp @@ -2203,6 +2203,17 @@ primop TraceEventOp "traceEvent#" GenPrimOp has_side_effects = True out_of_line = True +primop TraceMarkerOp "traceMarker#" GenPrimOp + Addr# -> State# s -> State# s + { Emits a marker event via the RTS tracing framework. The contents + of the event is the zero-terminated byte string passed as the first + argument. The event will be emitted either to the .eventlog file, + or to stderr, depending on the runtime RTS flags. } + with + has_side_effects = True + out_of_line = True + + ------------------------------------------------------------------------ --- --- ------------------------------------------------------------------------ diff --git a/includes/rts/EventLogFormat.h b/includes/rts/EventLogFormat.h index 82d3f683cc..e08a44996f 100644 --- a/includes/rts/EventLogFormat.h +++ b/includes/rts/EventLogFormat.h @@ -161,8 +161,8 @@ #define EVENT_TASK_CREATE 55 /* (taskID, cap, tid) */ #define EVENT_TASK_MIGRATE 56 /* (taskID, cap, new_cap) */ #define EVENT_TASK_DELETE 57 /* (taskID) */ - -/* Range 58 - 59 is available for new GHC and common events. */ +#define EVENT_USER_MARKER 58 /* (marker_name) */ +/* Range 59 - 59 is available for new GHC and common events. */ /* Range 60 - 80 is used by eden for parallel tracing * see http://www.mathematik.uni-marburg.de/~eden/ @@ -177,7 +177,7 @@ * 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_GHC_EVENT_TAGS 58 +#define NUM_GHC_EVENT_TAGS 59 #if 0 /* DEPRECATED EVENTS: */ /* we don't actually need to record the thread, it's implicit */ diff --git a/includes/stg/MiscClosures.h b/includes/stg/MiscClosures.h index b7b24a8632..760a59da49 100644 --- a/includes/stg/MiscClosures.h +++ b/includes/stg/MiscClosures.h @@ -431,6 +431,7 @@ RTS_FUN_DECL(stg_noDuplicatezh); RTS_FUN_DECL(stg_traceCcszh); RTS_FUN_DECL(stg_traceEventzh); +RTS_FUN_DECL(stg_traceMarkerzh); /* Other misc stuff */ // See wiki:Commentary/Compiler/Backends/PprC#Prototypes diff --git a/rts/Linker.c b/rts/Linker.c index 2d7e7d78a7..dca8a52813 100644 --- a/rts/Linker.c +++ b/rts/Linker.c @@ -1309,6 +1309,7 @@ typedef struct _RtsSymbolVal { SymI_HasProto(n_capabilities) \ SymI_HasProto(stg_traceCcszh) \ SymI_HasProto(stg_traceEventzh) \ + SymI_HasProto(stg_traceMarkerzh) \ SymI_HasProto(getMonotonicNSec) \ SymI_HasProto(lockFile) \ SymI_HasProto(unlockFile) \ diff --git a/rts/PrimOps.cmm b/rts/PrimOps.cmm index 1a531b2149..fb46cee0b5 100644 --- a/rts/PrimOps.cmm +++ b/rts/PrimOps.cmm @@ -2034,3 +2034,28 @@ stg_traceEventzh ( W_ msg ) return (); } +// Same code as stg_traceEventzh above but a different kind of event +// Before changing this code, read the comments in the impl above +stg_traceMarkerzh ( W_ msg ) +{ +#if defined(TRACING) || defined(DEBUG) + + ccall traceUserMarker(MyCapability() "ptr", msg "ptr"); + +#elif defined(DTRACE) + + W_ enabled; + +#if !defined(solaris2_TARGET_OS) + (enabled) = ccall __dtrace_isenabled$HaskellEvent$user__marker$v1(); +#else + enabled = 1; +#endif + if (enabled != 0) { + ccall dtraceUserMarkerWrapper(MyCapability() "ptr", msg "ptr"); + } + +#endif + return (); +} + diff --git a/rts/RtsProbes.d b/rts/RtsProbes.d index fd47b7574d..13f40f8201 100644 --- a/rts/RtsProbes.d +++ b/rts/RtsProbes.d @@ -99,4 +99,5 @@ provider HaskellEvent { /* probe log__msg (char *); */ /* we don't need EVENT_BLOCK_MARKER with dtrace */ probe user__msg (EventCapNo, char *); + probe user__marker (EventCapNo, char *); }; diff --git a/rts/Trace.c b/rts/Trace.c index 7a08c0f817..9da2115e2e 100644 --- a/rts/Trace.c +++ b/rts/Trace.c @@ -708,6 +708,28 @@ void traceUserMsg(Capability *cap, char *msg) traceFormatUserMsg(cap, "%s", msg); } +void traceUserMarker(Capability *cap, char *markername) +{ + /* Note: traceUserMarker is special since it has no wrapper (it's called + from cmm code), so we check eventlog_enabled and TRACE_user here. + */ +#ifdef DEBUG + if (RtsFlags.TraceFlags.tracing == TRACE_STDERR && TRACE_user) { + ACQUIRE_LOCK(&trace_utx); + tracePreface(); + debugBelch("cap %d: User marker: %s\n", cap->no, markername); + RELEASE_LOCK(&trace_utx); + } else +#endif + { + if (eventlog_enabled && TRACE_user) { + postUserMarker(cap, markername); + } + } + dtraceUserMarker(cap->no, markername); +} + + void traceThreadLabel_(Capability *cap, StgTSO *tso, char *label) diff --git a/rts/Trace.h b/rts/Trace.h index 4f1ac3bf0a..31aefcb58d 100644 --- a/rts/Trace.h +++ b/rts/Trace.h @@ -197,6 +197,12 @@ void trace_(char *msg, ...); */ void traceUserMsg(Capability *cap, char *msg); +/* + * A marker event emitted by the program + * Used by Debug.Trace.{traceMarker, traceMarkerIO} + */ +void traceUserMarker(Capability *cap, char *msg); + /* * An event to record a Haskell thread's label/name * Used by GHC.Conc.labelThread @@ -310,6 +316,7 @@ INLINE_HEADER void traceEventStartup_ (int n_caps STG_UNUSED) {}; #if !defined(DEBUG) && !defined(TRACING) && defined(DTRACE) void dtraceUserMsgWrapper(Capability *cap, char *msg); +void dtraceUserMarkerWrapper(Capability *cap, char *msg); #endif /* !defined(DEBUG) && !defined(TRACING) && defined(DTRACE) */ @@ -356,6 +363,8 @@ INLINE_HEADER void dtraceStartup (int num_caps) { HASKELLEVENT_CAP_DISABLE(cap) #define dtraceUserMsg(cap, msg) \ HASKELLEVENT_USER_MSG(cap, msg) +#define dtraceUserMarker(cap, msg) \ + HASKELLEVENT_USER_MARKER(cap, msg) #define dtraceGcIdle(cap) \ HASKELLEVENT_GC_IDLE(cap) #define dtraceGcWork(cap) \ @@ -435,6 +444,7 @@ INLINE_HEADER void dtraceStartup (int num_caps) { #define dtraceThreadLabel(cap, tso, label) /* nothing */ INLINE_HEADER void dtraceStartup (int num_caps STG_UNUSED) {}; #define dtraceUserMsg(cap, msg) /* nothing */ +#define dtraceUserMarker(cap, msg) /* nothing */ #define dtraceGcIdle(cap) /* nothing */ #define dtraceGcWork(cap) /* nothing */ #define dtraceGcDone(cap) /* nothing */ diff --git a/rts/eventlog/EventLog.c b/rts/eventlog/EventLog.c index 81aaecb67d..ef6f69c6dd 100644 --- a/rts/eventlog/EventLog.c +++ b/rts/eventlog/EventLog.c @@ -80,6 +80,7 @@ char *EventDesc[] = { [EVENT_CREATE_SPARK_THREAD] = "Create spark thread", [EVENT_LOG_MSG] = "Log message", [EVENT_USER_MSG] = "User message", + [EVENT_USER_MARKER] = "User marker", [EVENT_GC_IDLE] = "GC idle", [EVENT_GC_WORK] = "GC working", [EVENT_GC_DONE] = "GC done", @@ -369,6 +370,7 @@ initEventLogging(void) case EVENT_LOG_MSG: // (msg) case EVENT_USER_MSG: // (msg) + case EVENT_USER_MARKER: // (markername) case EVENT_RTS_IDENTIFIER: // (capset, str) case EVENT_PROGRAM_ARGS: // (capset, strvec) case EVENT_PROGRAM_ENV: // (capset, strvec) @@ -1086,6 +1088,27 @@ void postEventStartup(EventCapNo n_caps) RELEASE_LOCK(&eventBufMutex); } +void postUserMarker(Capability *cap, char *markername) +{ + EventsBuf *eb; + int size = strlen(markername); + + eb = &capEventBuf[cap->no]; + + if (!hasRoomForVariableEvent(eb, size)){ + printAndClearEventBuf(eb); + + if (!hasRoomForVariableEvent(eb, size)){ + // Event size exceeds buffer size, bail out: + return; + } + } + + postEventHeader(eb, EVENT_USER_MARKER); + postPayloadSize(eb, size); + postBuf(eb, (StgWord8*) markername, size); +} + void postThreadLabel(Capability *cap, EventThreadID id, char *label) diff --git a/rts/eventlog/EventLog.h b/rts/eventlog/EventLog.h index 5861f64757..85370e9843 100644 --- a/rts/eventlog/EventLog.h +++ b/rts/eventlog/EventLog.h @@ -49,6 +49,8 @@ void postUserMsg(Capability *cap, char *msg, va_list ap); void postCapMsg(Capability *cap, char *msg, va_list ap); +void postUserMarker(Capability *cap, char *markername); + void postEventStartup(EventCapNo n_caps); /* |