1 /* -----------------------------------------------------------------------------
3 * (c) The GHC Team 2006-2009
5 * Debug and performance tracing
7 * ---------------------------------------------------------------------------*/
19 #include "eventlog/EventLog.h"
28 // debugging flags, set with +RTS -D<something>
34 int DEBUG_block_alloc;
51 static Mutex trace_utx;
54 static rtsBool eventlog_enabled;
56 /* ---------------------------------------------------------------------------
57 Starting up / shuttting down the tracing facilities
58 --------------------------------------------------------------------------- */
60 void initTracing (void)
63 initMutex(&trace_utx);
67 #define DEBUG_FLAG(name, class) \
68 class = RtsFlags.DebugFlags.name ? 1 : 0;
70 DEBUG_FLAG(scheduler, DEBUG_sched);
72 DEBUG_FLAG(interpreter, DEBUG_interp);
73 DEBUG_FLAG(weak, DEBUG_weak);
74 DEBUG_FLAG(gccafs, DEBUG_gccafs);
75 DEBUG_FLAG(gc, DEBUG_gc);
76 DEBUG_FLAG(block_alloc, DEBUG_block_alloc);
77 DEBUG_FLAG(sanity, DEBUG_sanity);
78 DEBUG_FLAG(stable, DEBUG_stable);
79 DEBUG_FLAG(stm, DEBUG_stm);
80 DEBUG_FLAG(prof, DEBUG_prof);
81 DEBUG_FLAG(linker, DEBUG_linker);
82 DEBUG_FLAG(squeeze, DEBUG_squeeze);
83 DEBUG_FLAG(hpc, DEBUG_hpc);
84 DEBUG_FLAG(sparks, DEBUG_sparks);
87 // -Ds turns on scheduler tracing too
89 RtsFlags.TraceFlags.scheduler ||
90 RtsFlags.DebugFlags.scheduler;
92 eventlog_enabled = RtsFlags.TraceFlags.tracing == TRACE_EVENTLOG;
94 if (eventlog_enabled) {
99 void endTracing (void)
101 if (eventlog_enabled) {
106 void freeTracing (void)
108 if (eventlog_enabled) {
113 void resetTracing (void)
115 if (eventlog_enabled) {
116 abortEventLogging(); // abort eventlog inherited from parent
117 initEventLogging(); // child starts its own eventlog
121 /* ---------------------------------------------------------------------------
122 Emitting trace messages/events
123 --------------------------------------------------------------------------- */
126 static void tracePreface (void)
129 debugBelch("%12lx: ", (unsigned long)osThreadId());
131 if (RtsFlags.TraceFlags.timestamp) {
132 debugBelch("%9" FMT_Word64 ": ", stat_getElapsedTime());
138 static char *thread_stop_reasons[] = {
139 [HeapOverflow] = "heap overflow",
140 [StackOverflow] = "stack overflow",
141 [ThreadYielding] = "yielding",
142 [ThreadBlocked] = "blocked",
143 [ThreadFinished] = "finished",
144 [THREAD_SUSPENDED_FOREIGN_CALL] = "suspended while making a foreign call",
145 [6 + BlockedOnMVar] = "blocked on an MVar",
146 [6 + BlockedOnBlackHole] = "blocked on a black hole",
147 [6 + BlockedOnRead] = "blocked on a read operation",
148 [6 + BlockedOnWrite] = "blocked on a write operation",
149 [6 + BlockedOnDelay] = "blocked on a delay operation",
150 [6 + BlockedOnSTM] = "blocked on STM",
151 [6 + BlockedOnDoProc] = "blocked on asyncDoProc",
152 [6 + BlockedOnCCall] = "blocked on a foreign call",
153 [6 + BlockedOnCCall_Interruptible] = "blocked on a foreign call (interruptible)",
154 [6 + BlockedOnMsgThrowTo] = "blocked on throwTo",
155 [6 + ThreadMigrating] = "migrating"
160 static void traceSchedEvent_stderr (Capability *cap, EventTypeNum tag,
162 StgWord info1 STG_UNUSED,
163 StgWord info2 STG_UNUSED)
165 ACQUIRE_LOCK(&trace_utx);
169 case EVENT_CREATE_THREAD: // (cap, thread)
170 debugBelch("cap %d: created thread %lu\n",
171 cap->no, (lnat)tso->id);
173 case EVENT_RUN_THREAD: // (cap, thread)
174 debugBelch("cap %d: running thread %lu (%s)\n",
175 cap->no, (lnat)tso->id, what_next_strs[tso->what_next]);
177 case EVENT_THREAD_RUNNABLE: // (cap, thread)
178 debugBelch("cap %d: thread %lu appended to run queue\n",
179 cap->no, (lnat)tso->id);
181 case EVENT_RUN_SPARK: // (cap, thread)
182 debugBelch("cap %d: thread %lu running a spark\n",
183 cap->no, (lnat)tso->id);
185 case EVENT_CREATE_SPARK_THREAD: // (cap, spark_thread)
186 debugBelch("cap %d: creating spark thread %lu\n",
187 cap->no, (long)info1);
189 case EVENT_MIGRATE_THREAD: // (cap, thread, new_cap)
190 debugBelch("cap %d: thread %lu migrating to cap %d\n",
191 cap->no, (lnat)tso->id, (int)info1);
193 case EVENT_STEAL_SPARK: // (cap, thread, victim_cap)
194 debugBelch("cap %d: thread %lu stealing a spark from cap %d\n",
195 cap->no, (lnat)tso->id, (int)info1);
197 case EVENT_THREAD_WAKEUP: // (cap, thread, info1_cap)
198 debugBelch("cap %d: waking up thread %lu on cap %d\n",
199 cap->no, (lnat)tso->id, (int)info1);
202 case EVENT_STOP_THREAD: // (cap, thread, status)
203 if (info1 == 6 + BlockedOnBlackHole) {
204 debugBelch("cap %d: thread %lu stopped (blocked on black hole owned by thread %lu)\n",
205 cap->no, (lnat)tso->id, (long)info2);
207 debugBelch("cap %d: thread %lu stopped (%s)\n",
208 cap->no, (lnat)tso->id, thread_stop_reasons[info1]);
211 case EVENT_SHUTDOWN: // (cap)
212 debugBelch("cap %d: shutting down\n", cap->no);
214 case EVENT_REQUEST_SEQ_GC: // (cap)
215 debugBelch("cap %d: requesting sequential GC\n", cap->no);
217 case EVENT_REQUEST_PAR_GC: // (cap)
218 debugBelch("cap %d: requesting parallel GC\n", cap->no);
220 case EVENT_GC_START: // (cap)
221 debugBelch("cap %d: starting GC\n", cap->no);
223 case EVENT_GC_END: // (cap)
224 debugBelch("cap %d: finished GC\n", cap->no);
226 case EVENT_GC_IDLE: // (cap)
227 debugBelch("cap %d: GC idle\n", cap->no);
229 case EVENT_GC_WORK: // (cap)
230 debugBelch("cap %d: GC working\n", cap->no);
232 case EVENT_GC_DONE: // (cap)
233 debugBelch("cap %d: GC done\n", cap->no);
236 debugBelch("cap %d: thread %lu: event %d\n\n",
237 cap->no, (lnat)tso->id, tag);
241 RELEASE_LOCK(&trace_utx);
245 void traceSchedEvent_ (Capability *cap, EventTypeNum tag,
246 StgTSO *tso, StgWord info1, StgWord info2)
249 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
250 traceSchedEvent_stderr(cap, tag, tso, info1, info2);
254 postSchedEvent(cap,tag,tso ? tso->id : 0, info1, info2);
258 void traceCapsetModify_ (EventTypeNum tag,
264 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
265 ACQUIRE_LOCK(&trace_utx);
269 case EVENT_CAPSET_CREATE: // (capset, capset_type)
270 debugBelch("created capset %d of type %d\n", capset, other);
272 case EVENT_CAPSET_DELETE: // (capset)
273 debugBelch("deleted capset %d\n", capset);
275 case EVENT_CAPSET_ASSIGN_CAP: // (capset, capno)
276 debugBelch("assigned cap %d to capset %d\n", other, capset);
278 case EVENT_CAPSET_REMOVE_CAP: // (capset, capno)
279 debugBelch("removed cap %d from capset %d\n", other, capset);
282 RELEASE_LOCK(&trace_utx);
286 if(eventlog_enabled) postCapsetModifyEvent(tag, capset, other, other2);
290 extern char **environ;
292 void traceCapsetDetails_(int *argc, char **argv[]){
293 if(eventlog_enabled){
294 postCapsetModifyEvent(EVENT_OSPROCESS_PID,
295 CAPSET_OSPROCESS_DEFAULT,
300 snprintf(buf, sizeof(buf), "GHC-%s %s", ProjectVersion, RtsWay);
301 postCapsetStrEvent(EVENT_RTS_IDENTIFIER,
302 CAPSET_OSPROCESS_DEFAULT,
305 if(argc != NULL && argv != NULL){
306 postCapsetVecEvent(EVENT_PROGRAM_ARGS,
307 CAPSET_OSPROCESS_DEFAULT,
313 for( env_len = 0; environ[env_len] != NULL; env_len++);
314 postCapsetVecEvent(EVENT_PROGRAM_ENV,
315 CAPSET_OSPROCESS_DEFAULT,
321 void traceEvent_ (Capability *cap, EventTypeNum tag)
324 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
325 traceSchedEvent_stderr(cap, tag, 0, 0, 0);
334 static void traceCap_stderr(Capability *cap, char *msg, va_list ap)
336 ACQUIRE_LOCK(&trace_utx);
339 debugBelch("cap %d: ", cap->no);
343 RELEASE_LOCK(&trace_utx);
347 void traceCap_(Capability *cap, char *msg, ...)
353 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
354 traceCap_stderr(cap, msg, ap);
358 postCapMsg(cap, msg, ap);
365 static void trace_stderr(char *msg, va_list ap)
367 ACQUIRE_LOCK(&trace_utx);
373 RELEASE_LOCK(&trace_utx);
377 void trace_(char *msg, ...)
383 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
384 trace_stderr(msg, ap);
394 static void traceFormatUserMsg(Capability *cap, char *msg, ...)
400 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
401 traceCap_stderr(cap, msg, ap);
405 if (eventlog_enabled) {
406 postUserMsg(cap, msg, ap);
409 dtraceUserMsg(cap->no, msg);
412 void traceUserMsg(Capability *cap, char *msg)
414 traceFormatUserMsg(cap, "%s", msg);
417 void traceThreadStatus_ (StgTSO *tso USED_IF_DEBUG)
420 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
421 printThreadStatus(tso);
425 /* nothing - no event for this one yet */
431 void traceBegin (const char *str, ...)
436 ACQUIRE_LOCK(&trace_utx);
445 RELEASE_LOCK(&trace_utx);
451 // If DTRACE is enabled, but neither DEBUG nor TRACING, we need a C land
452 // wrapper for the user-msg probe (as we can't expand that in PrimOps.cmm)
454 #if !defined(DEBUG) && !defined(TRACING) && defined(DTRACE)
456 void dtraceUserMsgWrapper(Capability *cap, char *msg)
458 dtraceUserMsg(cap->no, msg);
461 #endif /* !defined(DEBUG) && !defined(TRACING) && defined(DTRACE) */