Commit 06456236 authored by Simon Marlow's avatar Simon Marlow

Optimise the code generated at trace points

parent 53628e91
......@@ -65,6 +65,12 @@ extern "C" {
#define END_RTS_PRIVATE /* disabled: END_RTS_PRIVATE */
#endif
#if __GNUC__ > 4
#define RTS_UNLIKELY(p) __builtin_expect((p),0)
#else
#define RTS_UNLIKELY(p) p
#endif
/* Fix for mingw stat problem (done here so it's early enough) */
#ifdef mingw32_HOST_OS
#define __MSVCRT__ 1
......
......@@ -19,7 +19,26 @@
#include "Threads.h"
#include "Printer.h"
StgWord32 classes_enabled; // not static due to inline funcs
// debugging flags, set with +RTS -D<something>
int DEBUG_sched;
int DEBUG_interp;
int DEBUG_weak;
int DEBUG_gccafs;
int DEBUG_gc;
int DEBUG_block_alloc;
int DEBUG_sanity;
int DEBUG_stable;
int DEBUG_stm;
int DEBUG_prof;
int DEBUG_gran;
int DEBUG_par;
int DEBUG_linker;
int DEBUG_squeeze;
int DEBUG_hpc;
int DEBUG_sparks;
// events
int TRACE_sched;
#ifdef THREADED_RTS
static Mutex trace_utx;
......@@ -37,7 +56,7 @@ void initTracing (void)
#ifdef DEBUG
#define DEBUG_FLAG(name, class) \
if (RtsFlags.DebugFlags.name) classes_enabled |= class;
class = RtsFlags.DebugFlags.name ? 1 : 0;
DEBUG_FLAG(scheduler, DEBUG_sched);
DEBUG_FLAG(scheduler, TRACE_sched); // -Ds enabled all sched events
......@@ -58,7 +77,7 @@ void initTracing (void)
#endif
#define TRACE_FLAG(name, class) \
if (RtsFlags.TraceFlags.name) classes_enabled |= class;
class = RtsFlags.TraceFlags.name ? 1 : 0;
TRACE_FLAG(scheduler, TRACE_sched);
......@@ -200,8 +219,11 @@ static void traceCap_stderr(Capability *cap, char *msg, va_list ap)
}
#endif
void traceCap_(Capability *cap, char *msg, va_list ap)
void traceCap_(Capability *cap, char *msg, ...)
{
va_list ap;
va_start(ap,msg);
#ifdef DEBUG
if (RtsFlags.TraceFlags.trace_stderr) {
traceCap_stderr(cap, msg, ap);
......@@ -210,6 +232,8 @@ void traceCap_(Capability *cap, char *msg, va_list ap)
{
postCapMsg(cap, msg, ap);
}
va_end(ap);
}
#ifdef DEBUG
......@@ -225,8 +249,11 @@ static void trace_stderr(char *msg, va_list ap)
}
#endif
void trace_(char *msg, va_list ap)
void trace_(char *msg, ...)
{
va_list ap;
va_start(ap,msg);
#ifdef DEBUG
if (RtsFlags.TraceFlags.trace_stderr) {
trace_stderr(msg, ap);
......@@ -235,6 +262,8 @@ void trace_(char *msg, va_list ap)
{
postMsg(msg, ap);
}
va_end(ap);
}
void traceThreadStatus_ (StgTSO *tso USED_IF_DEBUG)
......
......@@ -14,31 +14,6 @@
BEGIN_RTS_PRIVATE
// -----------------------------------------------------------------------------
// Posting events
// -----------------------------------------------------------------------------
INLINE_HEADER void trace (StgWord32 class, char *msg, ...);
#ifdef DEBUG
INLINE_HEADER void debugTrace (StgWord32 class, char *msg, ...);
#endif
INLINE_HEADER void traceSchedEvent (Capability *cap, EventTypeNum tag,
StgTSO *tso, StgWord64 other);
INLINE_HEADER void traceCap (StgWord32 class, Capability *cap,
char *msg, ...);
INLINE_HEADER void traceThreadStatus (StgWord32 class, StgTSO *tso);
INLINE_HEADER rtsBool traceClass (StgWord32 class);
#ifdef DEBUG
void traceBegin (const char *str, ...);
void traceEnd (void);
#endif
// -----------------------------------------------------------------------------
// EventLog API
// -----------------------------------------------------------------------------
......@@ -52,137 +27,111 @@ void freeTracing (void);
#endif /* TRACING */
// -----------------------------------------------------------------------------
// Message classes, these may be OR-ed together
// Message classes
// -----------------------------------------------------------------------------
// debugging flags, set with +RTS -D<something>
#define DEBUG_sched (1<<0)
#define DEBUG_interp (1<<1)
#define DEBUG_weak (1<<2)
#define DEBUG_gccafs (1<<3)
#define DEBUG_gc (1<<4)
#define DEBUG_block_alloc (1<<5)
#define DEBUG_sanity (1<<6)
#define DEBUG_stable (1<<7)
#define DEBUG_stm (1<<8)
#define DEBUG_prof (1<<9)
#define DEBUG_gran (1<<10)
#define DEBUG_par (1<<11)
#define DEBUG_linker (1<<12)
#define DEBUG_squeeze (1<<13)
#define DEBUG_hpc (1<<14)
#define DEBUG_sparks (1<<15)
extern int DEBUG_sched;
extern int DEBUG_interp;
extern int DEBUG_weak;
extern int DEBUG_gccafs;
extern int DEBUG_gc;
extern int DEBUG_block_alloc;
extern int DEBUG_sanity;
extern int DEBUG_stable;
extern int DEBUG_stm;
extern int DEBUG_prof;
extern int DEBUG_gran;
extern int DEBUG_par;
extern int DEBUG_linker;
extern int DEBUG_squeeze;
extern int DEBUG_hpc;
extern int DEBUG_sparks;
// events
#define TRACE_sched (1<<16)
extern int TRACE_sched;
// -----------------------------------------------------------------------------
// PRIVATE below here
// Posting events
//
// We use macros rather than inline functions deliberately. We want
// the not-taken case to be as efficient as possible, a simple
// test-and-jump, and with inline functions gcc seemed to move some of
// the instructions from the branch up before the test.
//
// -----------------------------------------------------------------------------
#ifdef TRACING
#ifdef DEBUG
void traceBegin (const char *str, ...);
void traceEnd (void);
#endif
extern StgWord32 classes_enabled;
#ifdef TRACING
INLINE_HEADER rtsBool traceClass (StgWord32 class)
{ return (classes_enabled & class); }
/*
* Record a scheduler event
*/
#define traceSchedEvent(cap, tag, tso, other) \
if (RTS_UNLIKELY(TRACE_sched)) { \
traceSchedEvent_(cap, tag, tso, other); \
}
void traceSchedEvent_ (Capability *cap, EventTypeNum tag,
StgTSO *tso, StgWord64 other);
// variadic macros are C99, and supported by gcc. However, the
// ##__VA_ARGS syntax is a gcc extension, which allows the variable
// argument list to be empty (see gcc docs for details).
/*
* Trace an event to the capability's event buffer.
* Emit a trace message on a particular Capability
*/
INLINE_HEADER void traceSchedEvent(Capability *cap, EventTypeNum tag,
StgTSO *tso, StgWord64 other)
{
if (traceClass(TRACE_sched)) {
traceSchedEvent_(cap, tag, tso, other);
#define traceCap(class, cap, msg, ...) \
if (RTS_UNLIKELY(class)) { \
traceCap_(cap, msg, ##__VA_ARGS__); \
}
}
void traceCap_(Capability *cap, char *msg, va_list ap);
void traceCap_(Capability *cap, char *msg, ...);
/*
* Trace a log message
* Emit a trace message
*/
INLINE_HEADER void traceCap (StgWord32 class, Capability *cap, char *msg, ...)
{
va_list ap;
va_start(ap,msg);
if (traceClass(class)) {
traceCap_(cap, msg, ap);
#define trace(class, msg, ...) \
if (RTS_UNLIKELY(class)) { \
trace_(msg, ##__VA_ARGS__); \
}
va_end(ap);
}
void trace_(char *msg, va_list ap);
void trace_(char *msg, ...);
/*
* Trace a log message
* Emit a debug message (only when DEBUG is defined)
*/
INLINE_HEADER void trace (StgWord32 class, char *msg, ...)
{
va_list ap;
va_start(ap,msg);
if (traceClass(class)) {
trace_(msg, ap);
}
va_end(ap);
}
#ifdef DEBUG
INLINE_HEADER void debugTrace (StgWord32 class, char *msg, ...)
{
va_list ap;
va_start(ap,msg);
if (traceClass(class)) {
trace_(msg, ap);
#define debugTrace(class, msg, ...) \
if (RTS_UNLIKELY(class)) { \
trace_(msg, ##__VA_ARGS__); \
}
va_end(ap);
}
#else
#define debugTrace(class, str, ...) /* nothing */
// variable arg macros are C99, and supported by gcc.
#endif
void traceThreadStatus_ (StgTSO *tso);
INLINE_HEADER void traceThreadStatus (StgWord32 class, StgTSO *tso)
{
if (traceClass(class)) {
traceThreadStatus_(tso);
/*
* Emit a message/event describing the state of a thread
*/
#define traceThreadStatus(class, tso) \
if (RTS_UNLIKELY(class)) { \
traceThreadStatus_(tso); \
}
}
#else /* !TRACING */
INLINE_HEADER rtsBool traceClass (StgWord32 class STG_UNUSED)
{ return rtsFalse; }
INLINE_HEADER void traceSchedEvent (Capability *cap STG_UNUSED,
EventTypeNum tag STG_UNUSED,
StgTSO *tso STG_UNUSED,
StgWord64 other STG_UNUSED)
{ /* nothing */ }
INLINE_HEADER void traceCap (StgWord32 class STG_UNUSED,
Capability *cap STG_UNUSED,
char *msg STG_UNUSED, ...)
{ /* nothing */ }
void traceThreadStatus_ (StgTSO *tso);
INLINE_HEADER void trace (StgWord32 class STG_UNUSED,
char *msg STG_UNUSED, ...)
{ /* nothing */ }
#else /* !TRACING */
#define traceSchedEvent(cap, tag, tso, other) /* nothing */
#define traceCap(class, cap, msg, ...) /* nothing */
#define trace(class, msg, ...) /* nothing */
#define debugTrace(class, str, ...) /* nothing */
// variable arg macros are C99, and supported by gcc.
INLINE_HEADER void traceThreadStatus (StgWord32 class STG_UNUSED,
StgTSO *tso STG_UNUSED)
{ /* nothing */ }
#define traceThreadStatus(class, tso) /* nothing */
#endif /* TRACING */
......
......@@ -279,7 +279,7 @@ GarbageCollect (rtsBool force_major_gc,
#ifdef DEBUG
// check for memory leaks if DEBUG is on
memInventory(traceClass(DEBUG_gc));
memInventory(DEBUG_gc);
#endif
// check stack sanity *before* GC
......@@ -782,7 +782,7 @@ SET_GCT(gc_threads[0]);
#ifdef DEBUG
// check for memory leaks if DEBUG is on
memInventory(traceClass(DEBUG_gc));
memInventory(DEBUG_gc);
#endif
#ifdef RTS_GTK_FRONTPANEL
......
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