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