1 /* -----------------------------------------------------------------------------
3 * (c) The GHC Team 2006-2009
5 * Debug and performance tracing
7 * ---------------------------------------------------------------------------*/
19 #include "eventlog/EventLog.h"
24 // debugging flags, set with +RTS -D<something>
30 int DEBUG_block_alloc;
47 static Mutex trace_utx;
50 static rtsBool eventlog_enabled;
52 /* ---------------------------------------------------------------------------
53 Starting up / shuttting down the tracing facilities
54 --------------------------------------------------------------------------- */
56 void initTracing (void)
59 initMutex(&trace_utx);
63 #define DEBUG_FLAG(name, class) \
64 class = RtsFlags.DebugFlags.name ? 1 : 0;
66 DEBUG_FLAG(scheduler, DEBUG_sched);
68 DEBUG_FLAG(interpreter, DEBUG_interp);
69 DEBUG_FLAG(weak, DEBUG_weak);
70 DEBUG_FLAG(gccafs, DEBUG_gccafs);
71 DEBUG_FLAG(gc, DEBUG_gc);
72 DEBUG_FLAG(block_alloc, DEBUG_block_alloc);
73 DEBUG_FLAG(sanity, DEBUG_sanity);
74 DEBUG_FLAG(stable, DEBUG_stable);
75 DEBUG_FLAG(stm, DEBUG_stm);
76 DEBUG_FLAG(prof, DEBUG_prof);
77 DEBUG_FLAG(linker, DEBUG_linker);
78 DEBUG_FLAG(squeeze, DEBUG_squeeze);
79 DEBUG_FLAG(hpc, DEBUG_hpc);
80 DEBUG_FLAG(sparks, DEBUG_sparks);
83 // -Ds turns on scheduler tracing too
85 RtsFlags.TraceFlags.scheduler ||
86 RtsFlags.DebugFlags.scheduler;
88 eventlog_enabled = RtsFlags.TraceFlags.tracing == TRACE_EVENTLOG;
90 if (eventlog_enabled) {
95 void endTracing (void)
97 if (eventlog_enabled) {
102 void freeTracing (void)
104 if (eventlog_enabled) {
109 /* ---------------------------------------------------------------------------
110 Emitting trace messages/events
111 --------------------------------------------------------------------------- */
114 static void tracePreface (void)
117 debugBelch("%12lx: ", (unsigned long)osThreadId());
119 if (RtsFlags.TraceFlags.timestamp) {
120 debugBelch("%9" FMT_Word64 ": ", stat_getElapsedTime());
126 static char *thread_stop_reasons[] = {
127 [HeapOverflow] = "heap overflow",
128 [StackOverflow] = "stack overflow",
129 [ThreadYielding] = "yielding",
130 [ThreadBlocked] = "blocked",
131 [ThreadFinished] = "finished",
132 [THREAD_SUSPENDED_FOREIGN_CALL] = "suspended while making a foreign call"
137 static void traceSchedEvent_stderr (Capability *cap, EventTypeNum tag,
139 StgWord64 other STG_UNUSED)
141 ACQUIRE_LOCK(&trace_utx);
145 case EVENT_CREATE_THREAD: // (cap, thread)
146 debugBelch("cap %d: created thread %lu\n",
147 cap->no, (lnat)tso->id);
149 case EVENT_RUN_THREAD: // (cap, thread)
150 debugBelch("cap %d: running thread %lu (%s)\n",
151 cap->no, (lnat)tso->id, what_next_strs[tso->what_next]);
153 case EVENT_THREAD_RUNNABLE: // (cap, thread)
154 debugBelch("cap %d: thread %lu appended to run queue\n",
155 cap->no, (lnat)tso->id);
157 case EVENT_RUN_SPARK: // (cap, thread)
158 debugBelch("cap %d: thread %lu running a spark\n",
159 cap->no, (lnat)tso->id);
161 case EVENT_CREATE_SPARK_THREAD: // (cap, spark_thread)
162 debugBelch("cap %d: creating spark thread %lu\n",
163 cap->no, (long)other);
165 case EVENT_MIGRATE_THREAD: // (cap, thread, new_cap)
166 debugBelch("cap %d: thread %lu migrating to cap %d\n",
167 cap->no, (lnat)tso->id, (int)other);
169 case EVENT_STEAL_SPARK: // (cap, thread, victim_cap)
170 debugBelch("cap %d: thread %lu stealing a spark from cap %d\n",
171 cap->no, (lnat)tso->id, (int)other);
173 case EVENT_THREAD_WAKEUP: // (cap, thread, other_cap)
174 debugBelch("cap %d: waking up thread %lu on cap %d\n",
175 cap->no, (lnat)tso->id, (int)other);
178 case EVENT_STOP_THREAD: // (cap, thread, status)
179 debugBelch("cap %d: thread %lu stopped (%s)\n",
180 cap->no, (lnat)tso->id, thread_stop_reasons[other]);
182 case EVENT_SHUTDOWN: // (cap)
183 debugBelch("cap %d: shutting down\n", cap->no);
185 case EVENT_REQUEST_SEQ_GC: // (cap)
186 debugBelch("cap %d: requesting sequential GC\n", cap->no);
188 case EVENT_REQUEST_PAR_GC: // (cap)
189 debugBelch("cap %d: requesting parallel GC\n", cap->no);
191 case EVENT_GC_START: // (cap)
192 debugBelch("cap %d: starting GC\n", cap->no);
194 case EVENT_GC_END: // (cap)
195 debugBelch("cap %d: finished GC\n", cap->no);
197 case EVENT_GC_IDLE: // (cap)
198 debugBelch("cap %d: GC idle\n", cap->no);
200 case EVENT_GC_WORK: // (cap)
201 debugBelch("cap %d: GC working\n", cap->no);
203 case EVENT_GC_DONE: // (cap)
204 debugBelch("cap %d: GC done\n", cap->no);
207 debugBelch("cap %2d: thread %lu: event %d\n\n",
208 cap->no, (lnat)tso->id, tag);
212 RELEASE_LOCK(&trace_utx);
216 void traceSchedEvent_ (Capability *cap, EventTypeNum tag,
217 StgTSO *tso, StgWord64 other)
220 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
221 traceSchedEvent_stderr(cap, tag, tso, other);
225 postSchedEvent(cap,tag,tso ? tso->id : 0,other);
229 void traceEvent_ (Capability *cap, EventTypeNum tag)
232 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
233 traceSchedEvent_stderr(cap, tag, 0, 0);
242 static void traceCap_stderr(Capability *cap, char *msg, va_list ap)
244 ACQUIRE_LOCK(&trace_utx);
247 debugBelch("cap %2d: ", cap->no);
251 RELEASE_LOCK(&trace_utx);
255 void traceCap_(Capability *cap, char *msg, ...)
261 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
262 traceCap_stderr(cap, msg, ap);
266 postCapMsg(cap, msg, ap);
273 static void trace_stderr(char *msg, va_list ap)
275 ACQUIRE_LOCK(&trace_utx);
281 RELEASE_LOCK(&trace_utx);
285 void trace_(char *msg, ...)
291 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
292 trace_stderr(msg, ap);
302 void traceUserMsg(Capability *cap, char *msg)
305 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
306 traceCap_stderr(cap, msg, NULL);
310 if (eventlog_enabled) {
311 postUserMsg(cap, msg);
314 dtraceUserMsg(cap->no, msg);
317 void traceThreadStatus_ (StgTSO *tso USED_IF_DEBUG)
320 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
321 printThreadStatus(tso);
325 /* nothing - no event for this one yet */
331 void traceBegin (const char *str, ...)
336 ACQUIRE_LOCK(&trace_utx);
345 RELEASE_LOCK(&trace_utx);
351 // If DTRACE is enabled, but neither DEBUG nor TRACING, we need a C land
352 // wrapper for the user-msg probe (as we can't expand that in PrimOps.cmm)
354 #if !defined(DEBUG) && !defined(TRACING) && defined(DTRACE)
356 void dtraceUserMsgWrapper(Capability *cap, char *msg)
358 dtraceUserMsg(cap->no, msg);
361 #endif /* !defined(DEBUG) && !defined(TRACING) && defined(DTRACE) */