Remove the DEBUG_<blah> variables, use RtsFlags directly
[ghc.git] / rts / Trace.c
1 /* -----------------------------------------------------------------------------
2 *
3 * (c) The GHC Team 2006-2009
4 *
5 * Debug and performance tracing
6 *
7 * ---------------------------------------------------------------------------*/
8
9 // external headers
10 #include "Rts.h"
11
12 // internal headers
13 #include "Trace.h"
14
15 #ifdef TRACING
16
17 #include "GetTime.h"
18 #include "GetEnv.h"
19 #include "Stats.h"
20 #include "eventlog/EventLog.h"
21 #include "Threads.h"
22 #include "Printer.h"
23
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27
28 // events
29 int TRACE_sched;
30 int TRACE_gc;
31 int TRACE_spark_sampled;
32 int TRACE_spark_full;
33 int TRACE_user;
34 int TRACE_cap;
35
36 #ifdef THREADED_RTS
37 static Mutex trace_utx;
38 #endif
39
40 static rtsBool eventlog_enabled;
41
42 /* ---------------------------------------------------------------------------
43 Starting up / shuttting down the tracing facilities
44 --------------------------------------------------------------------------- */
45
46 void initTracing (void)
47 {
48 #ifdef THREADED_RTS
49 initMutex(&trace_utx);
50 #endif
51
52 // -Ds turns on scheduler tracing too
53 TRACE_sched =
54 RtsFlags.TraceFlags.scheduler ||
55 RtsFlags.DebugFlags.scheduler;
56
57 // -Dg turns on gc tracing too
58 TRACE_gc =
59 RtsFlags.TraceFlags.gc ||
60 RtsFlags.DebugFlags.gc ||
61 RtsFlags.DebugFlags.scheduler;
62 if (TRACE_gc && RtsFlags.GcFlags.giveStats == NO_GC_STATS) {
63 RtsFlags.GcFlags.giveStats = COLLECT_GC_STATS;
64 }
65
66 TRACE_spark_sampled =
67 RtsFlags.TraceFlags.sparks_sampled;
68
69 // -Dr turns on full spark tracing
70 TRACE_spark_full =
71 RtsFlags.TraceFlags.sparks_full ||
72 RtsFlags.DebugFlags.sparks;
73
74 TRACE_user =
75 RtsFlags.TraceFlags.user;
76
77 // We trace cap events if we're tracing anything else
78 TRACE_cap =
79 TRACE_sched ||
80 TRACE_gc ||
81 TRACE_spark_sampled ||
82 TRACE_spark_full ||
83 TRACE_user;
84
85 eventlog_enabled = RtsFlags.TraceFlags.tracing == TRACE_EVENTLOG;
86
87 /* Note: we can have any of the TRACE_* flags turned on even when
88 eventlog_enabled is off. In the DEBUG way we may be tracing to stderr.
89 */
90
91 if (eventlog_enabled) {
92 initEventLogging();
93 }
94 }
95
96 void endTracing (void)
97 {
98 if (eventlog_enabled) {
99 endEventLogging();
100 }
101 }
102
103 void freeTracing (void)
104 {
105 if (eventlog_enabled) {
106 freeEventLogging();
107 }
108 }
109
110 void resetTracing (void)
111 {
112 if (eventlog_enabled) {
113 abortEventLogging(); // abort eventlog inherited from parent
114 initEventLogging(); // child starts its own eventlog
115 }
116 }
117
118 void tracingAddCapapilities (uint32_t from, uint32_t to)
119 {
120 if (eventlog_enabled) {
121 moreCapEventBufs(from,to);
122 }
123 }
124
125 /* ---------------------------------------------------------------------------
126 Emitting trace messages/events
127 --------------------------------------------------------------------------- */
128
129 #ifdef DEBUG
130 static void tracePreface (void)
131 {
132 #ifdef THREADED_RTS
133 debugBelch("%12lx: ", (unsigned long)osThreadId());
134 #endif
135 if (RtsFlags.TraceFlags.timestamp) {
136 debugBelch("%9" FMT_Word64 ": ", stat_getElapsedTime());
137 }
138 }
139 #endif
140
141 #ifdef DEBUG
142 static char *thread_stop_reasons[] = {
143 [HeapOverflow] = "heap overflow",
144 [StackOverflow] = "stack overflow",
145 [ThreadYielding] = "yielding",
146 [ThreadBlocked] = "blocked",
147 [ThreadFinished] = "finished",
148 [THREAD_SUSPENDED_FOREIGN_CALL] = "suspended while making a foreign call",
149 [6 + BlockedOnMVar] = "blocked on an MVar",
150 [6 + BlockedOnMVarRead] = "blocked on an atomic MVar read",
151 [6 + BlockedOnBlackHole] = "blocked on a black hole",
152 [6 + BlockedOnRead] = "blocked on a read operation",
153 [6 + BlockedOnWrite] = "blocked on a write operation",
154 [6 + BlockedOnDelay] = "blocked on a delay operation",
155 [6 + BlockedOnSTM] = "blocked on STM",
156 [6 + BlockedOnDoProc] = "blocked on asyncDoProc",
157 [6 + BlockedOnCCall] = "blocked on a foreign call",
158 [6 + BlockedOnCCall_Interruptible] = "blocked on a foreign call (interruptible)",
159 [6 + BlockedOnMsgThrowTo] = "blocked on throwTo",
160 [6 + ThreadMigrating] = "migrating"
161 };
162 #endif
163
164 #ifdef DEBUG
165 static void traceSchedEvent_stderr (Capability *cap, EventTypeNum tag,
166 StgTSO *tso,
167 StgWord info1 STG_UNUSED,
168 StgWord info2 STG_UNUSED)
169 {
170 ACQUIRE_LOCK(&trace_utx);
171
172 tracePreface();
173 switch (tag) {
174 case EVENT_CREATE_THREAD: // (cap, thread)
175 debugBelch("cap %d: created thread %" FMT_Word "\n",
176 cap->no, (W_)tso->id);
177 break;
178 case EVENT_RUN_THREAD: // (cap, thread)
179 debugBelch("cap %d: running thread %" FMT_Word " (%s)\n",
180 cap->no, (W_)tso->id, what_next_strs[tso->what_next]);
181 break;
182 case EVENT_THREAD_RUNNABLE: // (cap, thread)
183 debugBelch("cap %d: thread %" FMT_Word " appended to run queue\n",
184 cap->no, (W_)tso->id);
185 break;
186 case EVENT_MIGRATE_THREAD: // (cap, thread, new_cap)
187 debugBelch("cap %d: thread %" FMT_Word " migrating to cap %d\n",
188 cap->no, (W_)tso->id, (int)info1);
189 break;
190 case EVENT_THREAD_WAKEUP: // (cap, thread, info1_cap)
191 debugBelch("cap %d: waking up thread %" FMT_Word " on cap %d\n",
192 cap->no, (W_)tso->id, (int)info1);
193 break;
194
195 case EVENT_STOP_THREAD: // (cap, thread, status)
196 if (info1 == 6 + BlockedOnBlackHole) {
197 debugBelch("cap %d: thread %" FMT_Word " stopped (blocked on black hole owned by thread %lu)\n",
198 cap->no, (W_)tso->id, (long)info2);
199 } else {
200 debugBelch("cap %d: thread %" FMT_Word " stopped (%s)\n",
201 cap->no, (W_)tso->id, thread_stop_reasons[info1]);
202 }
203 break;
204 default:
205 debugBelch("cap %d: thread %" FMT_Word ": event %d\n\n",
206 cap->no, (W_)tso->id, tag);
207 break;
208 }
209
210 RELEASE_LOCK(&trace_utx);
211 }
212 #endif
213
214 void traceSchedEvent_ (Capability *cap, EventTypeNum tag,
215 StgTSO *tso, StgWord info1, StgWord info2)
216 {
217 #ifdef DEBUG
218 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
219 traceSchedEvent_stderr(cap, tag, tso, info1, info2);
220 } else
221 #endif
222 {
223 postSchedEvent(cap,tag,tso ? tso->id : 0, info1, info2);
224 }
225 }
226
227 #ifdef DEBUG
228 static void traceGcEvent_stderr (Capability *cap, EventTypeNum tag)
229 {
230 ACQUIRE_LOCK(&trace_utx);
231
232 tracePreface();
233 switch (tag) {
234 case EVENT_REQUEST_SEQ_GC: // (cap)
235 debugBelch("cap %d: requesting sequential GC\n", cap->no);
236 break;
237 case EVENT_REQUEST_PAR_GC: // (cap)
238 debugBelch("cap %d: requesting parallel GC\n", cap->no);
239 break;
240 case EVENT_GC_START: // (cap)
241 debugBelch("cap %d: starting GC\n", cap->no);
242 break;
243 case EVENT_GC_END: // (cap)
244 debugBelch("cap %d: finished GC\n", cap->no);
245 break;
246 case EVENT_GC_IDLE: // (cap)
247 debugBelch("cap %d: GC idle\n", cap->no);
248 break;
249 case EVENT_GC_WORK: // (cap)
250 debugBelch("cap %d: GC working\n", cap->no);
251 break;
252 case EVENT_GC_DONE: // (cap)
253 debugBelch("cap %d: GC done\n", cap->no);
254 break;
255 case EVENT_GC_GLOBAL_SYNC: // (cap)
256 debugBelch("cap %d: all caps stopped for GC\n", cap->no);
257 break;
258 default:
259 barf("traceGcEvent: unknown event tag %d", tag);
260 break;
261 }
262
263 RELEASE_LOCK(&trace_utx);
264 }
265 #endif
266
267 void traceGcEvent_ (Capability *cap, EventTypeNum tag)
268 {
269 #ifdef DEBUG
270 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
271 traceGcEvent_stderr(cap, tag);
272 } else
273 #endif
274 {
275 /* currently all GC events are nullary events */
276 postEvent(cap, tag);
277 }
278 }
279
280 void traceGcEventAtT_ (Capability *cap, StgWord64 ts, EventTypeNum tag)
281 {
282 #ifdef DEBUG
283 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
284 traceGcEvent_stderr(cap, tag);
285 } else
286 #endif
287 {
288 /* assuming nullary events and explicitly inserting a timestamp */
289 postEventAtTimestamp(cap, ts, tag);
290 }
291 }
292
293 void traceHeapEvent_ (Capability *cap,
294 EventTypeNum tag,
295 CapsetID heap_capset,
296 W_ info1)
297 {
298 #ifdef DEBUG
299 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
300 /* no stderr equivalent for these ones */
301 } else
302 #endif
303 {
304 postHeapEvent(cap, tag, heap_capset, info1);
305 }
306 }
307
308 void traceEventHeapInfo_ (CapsetID heap_capset,
309 uint32_t gens,
310 W_ maxHeapSize,
311 W_ allocAreaSize,
312 W_ mblockSize,
313 W_ blockSize)
314 {
315 #ifdef DEBUG
316 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
317 /* no stderr equivalent for these ones */
318 } else
319 #endif
320 {
321 postEventHeapInfo(heap_capset, gens,
322 maxHeapSize, allocAreaSize,
323 mblockSize, blockSize);
324 }
325 }
326
327 void traceEventGcStats_ (Capability *cap,
328 CapsetID heap_capset,
329 uint32_t gen,
330 W_ copied,
331 W_ slop,
332 W_ fragmentation,
333 uint32_t par_n_threads,
334 W_ par_max_copied,
335 W_ par_tot_copied)
336 {
337 #ifdef DEBUG
338 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
339 /* no stderr equivalent for these ones */
340 } else
341 #endif
342 {
343 postEventGcStats(cap, heap_capset, gen,
344 copied, slop, fragmentation,
345 par_n_threads, par_max_copied, par_tot_copied);
346 }
347 }
348
349 void traceCapEvent_ (Capability *cap,
350 EventTypeNum tag)
351 {
352 #ifdef DEBUG
353 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
354 ACQUIRE_LOCK(&trace_utx);
355
356 tracePreface();
357 switch (tag) {
358 case EVENT_CAP_CREATE: // (cap)
359 debugBelch("cap %d: initialised\n", cap->no);
360 break;
361 case EVENT_CAP_DELETE: // (cap)
362 debugBelch("cap %d: shutting down\n", cap->no);
363 break;
364 case EVENT_CAP_ENABLE: // (cap)
365 debugBelch("cap %d: enabling capability\n", cap->no);
366 break;
367 case EVENT_CAP_DISABLE: // (cap)
368 debugBelch("cap %d: disabling capability\n", cap->no);
369 break;
370 }
371 RELEASE_LOCK(&trace_utx);
372 } else
373 #endif
374 {
375 if (eventlog_enabled) {
376 postCapEvent(tag, (EventCapNo)cap->no);
377 }
378 }
379 }
380
381 void traceCapsetEvent_ (EventTypeNum tag,
382 CapsetID capset,
383 StgWord info)
384 {
385 #ifdef DEBUG
386 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR && TRACE_sched)
387 // When events go to stderr, it is annoying to see the capset
388 // events every time, so we only emit them with -Ds.
389 {
390 ACQUIRE_LOCK(&trace_utx);
391
392 tracePreface();
393 switch (tag) {
394 case EVENT_CAPSET_CREATE: // (capset, capset_type)
395 debugBelch("created capset %" FMT_Word32 " of type %d\n", capset,
396 (int)info);
397 break;
398 case EVENT_CAPSET_DELETE: // (capset)
399 debugBelch("deleted capset %" FMT_Word32 "\n", capset);
400 break;
401 case EVENT_CAPSET_ASSIGN_CAP: // (capset, capno)
402 debugBelch("assigned cap %" FMT_Word " to capset %" FMT_Word32 "\n",
403 info, capset);
404 break;
405 case EVENT_CAPSET_REMOVE_CAP: // (capset, capno)
406 debugBelch("removed cap %" FMT_Word " from capset %" FMT_Word32
407 "\n", info, capset);
408 break;
409 }
410 RELEASE_LOCK(&trace_utx);
411 } else
412 #endif
413 {
414 if (eventlog_enabled) {
415 postCapsetEvent(tag, capset, info);
416 }
417 }
418 }
419
420 void traceWallClockTime_(void) {
421 if (eventlog_enabled) {
422 postWallClockTime(CAPSET_CLOCKDOMAIN_DEFAULT);
423 }
424 }
425
426 void traceOSProcessInfo_(void) {
427 if (eventlog_enabled) {
428 postCapsetEvent(EVENT_OSPROCESS_PID,
429 CAPSET_OSPROCESS_DEFAULT,
430 getpid());
431
432 #if !defined (mingw32_HOST_OS)
433 /* Windows has no strong concept of process hierarchy, so no getppid().
434 * In any case, this trace event is mainly useful for tracing programs
435 * that use 'forkProcess' which Windows doesn't support anyway.
436 */
437 postCapsetEvent(EVENT_OSPROCESS_PPID,
438 CAPSET_OSPROCESS_DEFAULT,
439 getppid());
440 #endif
441 {
442 char buf[256];
443 snprintf(buf, sizeof(buf), "GHC-%s %s", ProjectVersion, RtsWay);
444 postCapsetStrEvent(EVENT_RTS_IDENTIFIER,
445 CAPSET_OSPROCESS_DEFAULT,
446 buf);
447 }
448 {
449 int argc = 0; char **argv;
450 getFullProgArgv(&argc, &argv);
451 if (argc != 0) {
452 postCapsetVecEvent(EVENT_PROGRAM_ARGS,
453 CAPSET_OSPROCESS_DEFAULT,
454 argc, argv);
455 }
456 }
457 {
458 int envc = 0; char **envv;
459 getProgEnvv(&envc, &envv);
460 if (envc != 0) {
461 postCapsetVecEvent(EVENT_PROGRAM_ENV,
462 CAPSET_OSPROCESS_DEFAULT,
463 envc, envv);
464 }
465 freeProgEnvv(envc, envv);
466 }
467 }
468 }
469
470 #ifdef DEBUG
471 static void traceSparkEvent_stderr (Capability *cap, EventTypeNum tag,
472 StgWord info1)
473 {
474 ACQUIRE_LOCK(&trace_utx);
475
476 tracePreface();
477 switch (tag) {
478
479 case EVENT_CREATE_SPARK_THREAD: // (cap, spark_thread)
480 debugBelch("cap %d: creating spark thread %lu\n",
481 cap->no, (long)info1);
482 break;
483 case EVENT_SPARK_CREATE: // (cap)
484 debugBelch("cap %d: added spark to pool\n",
485 cap->no);
486 break;
487 case EVENT_SPARK_DUD: // (cap)
488 debugBelch("cap %d: discarded dud spark\n",
489 cap->no);
490 break;
491 case EVENT_SPARK_OVERFLOW: // (cap)
492 debugBelch("cap %d: discarded overflowed spark\n",
493 cap->no);
494 break;
495 case EVENT_SPARK_RUN: // (cap)
496 debugBelch("cap %d: running a spark\n",
497 cap->no);
498 break;
499 case EVENT_SPARK_STEAL: // (cap, victim_cap)
500 debugBelch("cap %d: stealing a spark from cap %d\n",
501 cap->no, (int)info1);
502 break;
503 case EVENT_SPARK_FIZZLE: // (cap)
504 debugBelch("cap %d: fizzled spark removed from pool\n",
505 cap->no);
506 break;
507 case EVENT_SPARK_GC: // (cap)
508 debugBelch("cap %d: GCd spark removed from pool\n",
509 cap->no);
510 break;
511 default:
512 barf("traceSparkEvent: unknown event tag %d", tag);
513 break;
514 }
515
516 RELEASE_LOCK(&trace_utx);
517 }
518 #endif
519
520 void traceSparkEvent_ (Capability *cap, EventTypeNum tag, StgWord info1)
521 {
522 #ifdef DEBUG
523 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
524 traceSparkEvent_stderr(cap, tag, info1);
525 } else
526 #endif
527 {
528 postSparkEvent(cap,tag,info1);
529 }
530 }
531
532 void traceSparkCounters_ (Capability *cap,
533 SparkCounters counters,
534 StgWord remaining)
535 {
536 #ifdef DEBUG
537 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
538 /* we currently don't do debug tracing of spark stats but we must
539 test for TRACE_STDERR because of the !eventlog_enabled case. */
540 } else
541 #endif
542 {
543 postSparkCountersEvent(cap, counters, remaining);
544 }
545 }
546
547 void traceTaskCreate_ (Task *task,
548 Capability *cap)
549 {
550 #ifdef DEBUG
551 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
552 /* We currently don't do debug tracing of tasks but we must
553 test for TRACE_STDERR because of the !eventlog_enabled case. */
554 } else
555 #endif
556 {
557 EventTaskId taskid = serialisableTaskId(task);
558 EventKernelThreadId tid = kernelThreadId();
559 postTaskCreateEvent(taskid, cap->no, tid);
560 }
561 }
562
563 void traceTaskMigrate_ (Task *task,
564 Capability *cap,
565 Capability *new_cap)
566 {
567 #ifdef DEBUG
568 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
569 /* We currently don't do debug tracing of tasks but we must
570 test for TRACE_STDERR because of the !eventlog_enabled case. */
571 } else
572 #endif
573 {
574 EventTaskId taskid = serialisableTaskId(task);
575 postTaskMigrateEvent(taskid, cap->no, new_cap->no);
576 }
577 }
578
579 void traceTaskDelete_ (Task *task)
580 {
581 #ifdef DEBUG
582 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
583 /* We currently don't do debug tracing of tasks but we must
584 test for TRACE_STDERR because of the !eventlog_enabled case. */
585 } else
586 #endif
587 {
588 EventTaskId taskid = serialisableTaskId(task);
589 postTaskDeleteEvent(taskid);
590 }
591 }
592
593 void traceHeapProfBegin(StgWord8 profile_id)
594 {
595 if (eventlog_enabled) {
596 postHeapProfBegin(profile_id);
597 }
598 }
599
600 void traceHeapProfSampleBegin(StgInt era)
601 {
602 if (eventlog_enabled) {
603 postHeapProfSampleBegin(era);
604 }
605 }
606
607 void traceHeapProfSampleString(StgWord8 profile_id,
608 const char *label, StgWord residency)
609 {
610 if (eventlog_enabled) {
611 postHeapProfSampleString(profile_id, label, residency);
612 }
613 }
614
615 #ifdef PROFILING
616 void traceHeapProfCostCentre(StgWord32 ccID,
617 const char *label,
618 const char *module,
619 const char *srcloc,
620 StgBool is_caf)
621 {
622 if (eventlog_enabled) {
623 postHeapProfCostCentre(ccID, label, module, srcloc, is_caf);
624 }
625 }
626
627 void traceHeapProfSampleCostCentre(StgWord8 profile_id,
628 CostCentreStack *stack, StgWord residency)
629 {
630 if (eventlog_enabled) {
631 postHeapProfSampleCostCentre(profile_id, stack, residency);
632 }
633 }
634 #endif
635
636 #ifdef DEBUG
637 static void vtraceCap_stderr(Capability *cap, char *msg, va_list ap)
638 {
639 ACQUIRE_LOCK(&trace_utx);
640
641 tracePreface();
642 debugBelch("cap %d: ", cap->no);
643 vdebugBelch(msg,ap);
644 debugBelch("\n");
645
646 RELEASE_LOCK(&trace_utx);
647 }
648
649 static void traceCap_stderr(Capability *cap, char *msg, ...)
650 {
651 va_list ap;
652 va_start(ap,msg);
653 vtraceCap_stderr(cap, msg, ap);
654 va_end(ap);
655 }
656 #endif
657
658 void traceCap_(Capability *cap, char *msg, ...)
659 {
660 va_list ap;
661 va_start(ap,msg);
662
663 #ifdef DEBUG
664 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
665 vtraceCap_stderr(cap, msg, ap);
666 } else
667 #endif
668 {
669 postCapMsg(cap, msg, ap);
670 }
671
672 va_end(ap);
673 }
674
675 #ifdef DEBUG
676 static void vtrace_stderr(char *msg, va_list ap)
677 {
678 ACQUIRE_LOCK(&trace_utx);
679
680 tracePreface();
681 vdebugBelch(msg,ap);
682 debugBelch("\n");
683
684 RELEASE_LOCK(&trace_utx);
685 }
686 #endif
687
688 void trace_(char *msg, ...)
689 {
690 va_list ap;
691 va_start(ap,msg);
692
693 #ifdef DEBUG
694 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
695 vtrace_stderr(msg, ap);
696 } else
697 #endif
698 {
699 postMsg(msg, ap);
700 }
701
702 va_end(ap);
703 }
704
705 void traceUserMsg(Capability *cap, char *msg)
706 {
707 /* Note: normally we don't check the TRACE_* flags here as they're checked
708 by the wrappers in Trace.h. But traceUserMsg is special since it has no
709 wrapper (it's called from cmm code), so we check TRACE_user here
710 */
711 #ifdef DEBUG
712 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR && TRACE_user) {
713 // Use "%s" as format string to ignore format specifiers in msg (#3874).
714 traceCap_stderr(cap, "%s", msg);
715 } else
716 #endif
717 {
718 if (eventlog_enabled && TRACE_user) {
719 postUserEvent(cap, EVENT_USER_MSG, msg);
720 }
721 }
722 dtraceUserMsg(cap->no, msg);
723 }
724
725 void traceUserMarker(Capability *cap, char *markername)
726 {
727 /* Note: traceUserMarker is special since it has no wrapper (it's called
728 from cmm code), so we check eventlog_enabled and TRACE_user here.
729 */
730 #ifdef DEBUG
731 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR && TRACE_user) {
732 traceCap_stderr(cap, "User marker: %s", markername);
733 } else
734 #endif
735 {
736 if (eventlog_enabled && TRACE_user) {
737 postUserEvent(cap, EVENT_USER_MARKER, markername);
738 }
739 }
740 dtraceUserMarker(cap->no, markername);
741 }
742
743
744 void traceThreadLabel_(Capability *cap,
745 StgTSO *tso,
746 char *label)
747 {
748 #ifdef DEBUG
749 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
750 ACQUIRE_LOCK(&trace_utx);
751 tracePreface();
752 debugBelch("cap %d: thread %" FMT_Word " has label %s\n",
753 cap->no, (W_)tso->id, label);
754 RELEASE_LOCK(&trace_utx);
755 } else
756 #endif
757 {
758 postThreadLabel(cap, tso->id, label);
759 }
760 }
761
762 void traceThreadStatus_ (StgTSO *tso USED_IF_DEBUG)
763 {
764 #ifdef DEBUG
765 if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
766 printThreadStatus(tso);
767 } else
768 #endif
769 {
770 /* nothing - no event for this one yet */
771 }
772 }
773
774 #ifdef DEBUG
775 void traceBegin (const char *str, ...)
776 {
777 va_list ap;
778 va_start(ap,str);
779
780 ACQUIRE_LOCK(&trace_utx);
781
782 tracePreface();
783 vdebugBelch(str,ap);
784 va_end(ap);
785 }
786
787 void traceEnd (void)
788 {
789 debugBelch("\n");
790 RELEASE_LOCK(&trace_utx);
791 }
792 #endif /* DEBUG */
793
794 #endif /* TRACING */
795
796 // If DTRACE is enabled, but neither DEBUG nor TRACING, we need a C land
797 // wrapper for the user-msg probe (as we can't expand that in PrimOps.cmm)
798 //
799 #if !defined(DEBUG) && !defined(TRACING) && defined(DTRACE)
800
801 void dtraceUserMsgWrapper(Capability *cap, char *msg)
802 {
803 dtraceUserMsg(cap->no, msg);
804 }
805
806 void dtraceUserMarkerWrapper(Capability *cap, char *msg)
807 {
808 dtraceUserMarker(cap->no, msg);
809 }
810
811 #endif /* !defined(DEBUG) && !defined(TRACING) && defined(DTRACE) */