NCGMonad: Add MonadUnique NatM instance
[ghc.git] / rts / Trace.h
1 /* -----------------------------------------------------------------------------
2 *
3 * (c) The GHC Team, 2008-2009
4 *
5 * Support for fast binary event logging and user-space dtrace probes.
6 *
7 * ---------------------------------------------------------------------------*/
8
9 #ifndef TRACE_H
10 #define TRACE_H
11
12 #include "rts/EventLogFormat.h"
13 #include "Capability.h"
14
15 #if defined(DTRACE)
16 #include "RtsProbes.h"
17 #endif /* defined(DTRACE) */
18
19 #include "BeginPrivate.h"
20
21 // -----------------------------------------------------------------------------
22 // EventLog API
23 // -----------------------------------------------------------------------------
24
25 #if defined(TRACING)
26
27 void initTracing (void);
28 void endTracing (void);
29 void freeTracing (void);
30 void resetTracing (void);
31 void tracingAddCapapilities (uint32_t from, uint32_t to);
32
33 #endif /* TRACING */
34
35 typedef StgWord32 CapsetID;
36 typedef StgWord16 CapsetType;
37 enum CapsetType { CapsetTypeCustom = CAPSET_TYPE_CUSTOM,
38 CapsetTypeOsProcess = CAPSET_TYPE_OSPROCESS,
39 CapsetTypeClockdomain = CAPSET_TYPE_CLOCKDOMAIN };
40 #define CAPSET_OSPROCESS_DEFAULT ((CapsetID)0)
41 #define CAPSET_HEAP_DEFAULT ((CapsetID)0) /* reusing the same capset */
42 #define CAPSET_CLOCKDOMAIN_DEFAULT ((CapsetID)1)
43
44 // -----------------------------------------------------------------------------
45 // Message classes
46 // -----------------------------------------------------------------------------
47
48 // shorthand for RtsFlags.DebugFlags.<blah>, useful with debugTrace()
49 #define DEBUG_sched RtsFlags.DebugFlags.scheduler
50 #define DEBUG_interp RtsFlags.DebugFlags.interp
51 #define DEBUG_weak RtsFlags.DebugFlags.weak
52 #define DEBUG_gccafs RtsFlags.DebugFlags.gccafs
53 #define DEBUG_gc RtsFlags.DebugFlags.gc
54 #define DEBUG_block_alloc RtsFlags.DebugFlags.alloc
55 #define DEBUG_sanity RtsFlags.DebugFlags.sanity
56 #define DEBUG_stable RtsFlags.DebugFlags.stable
57 #define DEBUG_stm RtsFlags.DebugFlags.stm
58 #define DEBUG_prof RtsFlags.DebugFlags.prof
59 #define DEBUG_gran RtsFlags.DebugFlags.gran
60 #define DEBUG_par RtsFlags.DebugFlags.par
61 #define DEBUG_linker RtsFlags.DebugFlags.linker
62 #define DEBUG_squeeze RtsFlags.DebugFlags.squeeze
63 #define DEBUG_hpc RtsFlags.DebugFlags.hpc
64 #define DEBUG_sparks RtsFlags.DebugFlags.sparks
65
66 // events
67 extern int TRACE_sched;
68 extern int TRACE_gc;
69 extern int TRACE_spark_sampled;
70 extern int TRACE_spark_full;
71 /* extern int TRACE_user; */ // only used in Trace.c
72 extern int TRACE_cap;
73
74 // -----------------------------------------------------------------------------
75 // Posting events
76 //
77 // We use macros rather than inline functions deliberately. We want
78 // the not-taken case to be as efficient as possible, a simple
79 // test-and-jump, and with inline functions gcc seemed to move some of
80 // the instructions from the branch up before the test.
81 //
82 // -----------------------------------------------------------------------------
83
84 #ifdef DEBUG
85 void traceBegin (const char *str, ...);
86 void traceEnd (void);
87 #endif
88
89 #ifdef TRACING
90
91 /*
92 * Record a scheduler event
93 */
94 #define traceSchedEvent(cap, tag, tso, other) \
95 if (RTS_UNLIKELY(TRACE_sched)) { \
96 traceSchedEvent_(cap, tag, tso, other, 0); \
97 }
98
99 #define traceSchedEvent2(cap, tag, tso, info1, info2) \
100 if (RTS_UNLIKELY(TRACE_sched)) { \
101 traceSchedEvent_(cap, tag, tso, info1, info2); \
102 }
103
104 void traceSchedEvent_ (Capability *cap, EventTypeNum tag,
105 StgTSO *tso, StgWord info1, StgWord info2);
106
107 /*
108 * Record a GC event
109 */
110 #define traceGcEvent(cap, tag) \
111 if (RTS_UNLIKELY(TRACE_gc)) { \
112 traceGcEvent_(cap, tag); \
113 }
114
115 void traceGcEvent_ (Capability *cap, EventTypeNum tag);
116
117 /*
118 * Record a GC event at the explicitly given timestamp
119 */
120 #define traceGcEventAtT(cap, ts, tag) \
121 if (RTS_UNLIKELY(TRACE_gc)) { \
122 traceGcEventAtT_(cap, ts, tag); \
123 }
124
125 void traceGcEventAtT_ (Capability *cap, StgWord64 ts, EventTypeNum tag);
126
127 /*
128 * Record a heap event
129 */
130 #define traceHeapEvent(cap, tag, heap_capset, info1) \
131 if (RTS_UNLIKELY(TRACE_gc)) { \
132 traceHeapEvent_(cap, tag, heap_capset, info1); \
133 }
134 void traceHeapEvent_ (Capability *cap,
135 EventTypeNum tag,
136 CapsetID heap_capset,
137 W_ info1);
138
139 void traceEventHeapInfo_ (CapsetID heap_capset,
140 uint32_t gens,
141 W_ maxHeapSize,
142 W_ allocAreaSize,
143 W_ mblockSize,
144 W_ blockSize);
145
146 void traceEventGcStats_ (Capability *cap,
147 CapsetID heap_capset,
148 uint32_t gen,
149 W_ copied,
150 W_ slop,
151 W_ fragmentation,
152 uint32_t par_n_threads,
153 W_ par_max_copied,
154 W_ par_tot_copied);
155
156 /*
157 * Record a spark event
158 */
159 #define traceSparkEvent(cap, tag) \
160 if (RTS_UNLIKELY(TRACE_spark_full)) { \
161 traceSparkEvent_(cap, tag, 0); \
162 }
163
164 #define traceSparkEvent2(cap, tag, other) \
165 if (RTS_UNLIKELY(TRACE_spark_full)) { \
166 traceSparkEvent_(cap, tag, other); \
167 }
168
169 void traceSparkEvent_ (Capability *cap, EventTypeNum tag, StgWord info1);
170
171 // variadic macros are C99, and supported by gcc. However, the
172 // ##__VA_ARGS syntax is a gcc extension, which allows the variable
173 // argument list to be empty (see gcc docs for details).
174
175 /*
176 * Emit a trace message on a particular Capability
177 */
178 #define traceCap(class, cap, msg, ...) \
179 if (RTS_UNLIKELY(class)) { \
180 traceCap_(cap, msg, ##__VA_ARGS__); \
181 }
182
183 void traceCap_(Capability *cap, char *msg, ...);
184
185 /*
186 * Emit a trace message
187 */
188 #define trace(class, msg, ...) \
189 if (RTS_UNLIKELY(class)) { \
190 trace_(msg, ##__VA_ARGS__); \
191 }
192
193 void trace_(char *msg, ...);
194
195 /*
196 * A message or event emitted by the program
197 * Used by Debug.Trace.{traceEvent, traceEventIO}
198 */
199 void traceUserMsg(Capability *cap, char *msg);
200
201 /*
202 * A marker event emitted by the program
203 * Used by Debug.Trace.{traceMarker, traceMarkerIO}
204 */
205 void traceUserMarker(Capability *cap, char *msg);
206
207 /*
208 * An event to record a Haskell thread's label/name
209 * Used by GHC.Conc.labelThread
210 */
211 void traceThreadLabel_(Capability *cap,
212 StgTSO *tso,
213 char *label);
214
215 /*
216 * Emit a debug message (only when DEBUG is defined)
217 */
218 #ifdef DEBUG
219 #define debugTrace(class, msg, ...) \
220 if (RTS_UNLIKELY(class)) { \
221 trace_(msg, ##__VA_ARGS__); \
222 }
223 #else
224 #define debugTrace(class, str, ...) /* nothing */
225 #endif
226
227 #ifdef DEBUG
228 #define debugTraceCap(class, cap, msg, ...) \
229 if (RTS_UNLIKELY(class)) { \
230 traceCap_(cap, msg, ##__VA_ARGS__); \
231 }
232 #else
233 #define debugTraceCap(class, cap, str, ...) /* nothing */
234 #endif
235
236 /*
237 * Emit a message/event describing the state of a thread
238 */
239 #define traceThreadStatus(class, tso) \
240 if (RTS_UNLIKELY(class)) { \
241 traceThreadStatus_(tso); \
242 }
243
244 void traceThreadStatus_ (StgTSO *tso);
245
246 /*
247 * Events for describing capabilities and capability sets in the eventlog
248 */
249 #define traceCapEvent(cap, tag) \
250 if (RTS_UNLIKELY(TRACE_cap)) { \
251 traceCapEvent_(cap, tag); \
252 }
253
254 void traceCapEvent_ (Capability *cap,
255 EventTypeNum tag);
256
257 #define traceCapsetEvent(cap, capset, info) \
258 if (RTS_UNLIKELY(TRACE_cap)) { \
259 traceCapsetEvent_(cap, capset, info); \
260 }
261
262 void traceCapsetEvent_ (EventTypeNum tag,
263 CapsetID capset,
264 StgWord info);
265
266 void traceWallClockTime_(void);
267
268 void traceOSProcessInfo_ (void);
269
270 void traceSparkCounters_ (Capability *cap,
271 SparkCounters counters,
272 StgWord remaining);
273
274 void traceTaskCreate_ (Task *task,
275 Capability *cap);
276
277 void traceTaskMigrate_ (Task *task,
278 Capability *cap,
279 Capability *new_cap);
280
281 void traceTaskDelete_ (Task *task);
282
283 void traceHeapProfBegin(StgWord8 profile_id);
284 void traceHeapProfSampleBegin(StgInt era);
285 void traceHeapProfSampleString(StgWord8 profile_id,
286 const char *label, StgWord residency);
287 #ifdef PROFILING
288 void traceHeapProfCostCentre(StgWord32 ccID,
289 const char *label,
290 const char *module,
291 const char *srcloc,
292 StgBool is_caf);
293 void traceHeapProfSampleCostCentre(StgWord8 profile_id,
294 CostCentreStack *stack, StgWord residency);
295 #endif /* PROFILING */
296
297 #else /* !TRACING */
298
299 #define traceSchedEvent(cap, tag, tso, other) /* nothing */
300 #define traceSchedEvent2(cap, tag, tso, other, info) /* nothing */
301 #define traceGcEvent(cap, tag) /* nothing */
302 #define traceGcEventAtT(cap, ts, tag) /* nothing */
303 #define traceEventGcStats_(cap, heap_capset, gen, \
304 copied, slop, fragmentation, \
305 par_n_threads, par_max_copied, par_tot_copied) /* nothing */
306 #define traceHeapEvent(cap, tag, heap_capset, info1) /* nothing */
307 #define traceEventHeapInfo_(heap_capset, gens, \
308 maxHeapSize, allocAreaSize, \
309 mblockSize, blockSize) /* nothing */
310 #define traceSparkEvent(cap, tag) /* nothing */
311 #define traceSparkEvent2(cap, tag, other) /* nothing */
312 #define traceCap(class, cap, msg, ...) /* nothing */
313 #define trace(class, msg, ...) /* nothing */
314 #define debugTrace(class, str, ...) /* nothing */
315 #define debugTraceCap(class, cap, str, ...) /* nothing */
316 #define traceThreadStatus(class, tso) /* nothing */
317 #define traceThreadLabel_(cap, tso, label) /* nothing */
318 #define traceCapEvent(cap, tag) /* nothing */
319 #define traceCapsetEvent(tag, capset, info) /* nothing */
320 #define traceWallClockTime_() /* nothing */
321 #define traceOSProcessInfo_() /* nothing */
322 #define traceSparkCounters_(cap, counters, remaining) /* nothing */
323 #define traceTaskCreate_(taskID, cap) /* nothing */
324 #define traceTaskMigrate_(taskID, cap, new_cap) /* nothing */
325 #define traceTaskDelete_(taskID) /* nothing */
326 #define traceHeapProfBegin(profile_id) /* nothing */
327 #define traceHeapProfCostCentre(ccID, label, module, srcloc, is_caf) /* nothing */
328 #define traceHeapProfSampleBegin(era) /* nothing */
329 #define traceHeapProfSampleCostCentre(profile_id, stack, residency) /* nothing */
330 #define traceHeapProfSampleString(profile_id, label, residency) /* nothing */
331
332 #endif /* TRACING */
333
334 // If DTRACE is enabled, but neither DEBUG nor TRACING, we need a C land
335 // wrapper for the user-msg probe (as we can't expand that in PrimOps.cmm)
336 //
337 #if !defined(DEBUG) && !defined(TRACING) && defined(DTRACE)
338
339 void dtraceUserMsgWrapper(Capability *cap, char *msg);
340 void dtraceUserMarkerWrapper(Capability *cap, char *msg);
341
342 #endif /* !defined(DEBUG) && !defined(TRACING) && defined(DTRACE) */
343
344 // -----------------------------------------------------------------------------
345 // Aliases for static dtrace probes if dtrace is available
346 // -----------------------------------------------------------------------------
347
348 #if defined(DTRACE)
349
350 #define dtraceCreateThread(cap, tid) \
351 HASKELLEVENT_CREATE_THREAD(cap, tid)
352 #define dtraceRunThread(cap, tid) \
353 HASKELLEVENT_RUN_THREAD(cap, tid)
354 #define dtraceStopThread(cap, tid, status, info) \
355 HASKELLEVENT_STOP_THREAD(cap, tid, status, info)
356 #define dtraceThreadRunnable(cap, tid) \
357 HASKELLEVENT_THREAD_RUNNABLE(cap, tid)
358 #define dtraceMigrateThread(cap, tid, new_cap) \
359 HASKELLEVENT_MIGRATE_THREAD(cap, tid, new_cap)
360 #define dtraceThreadWakeup(cap, tid, other_cap) \
361 HASKELLEVENT_THREAD_WAKEUP(cap, tid, other_cap)
362 #define dtraceGcStart(cap) \
363 HASKELLEVENT_GC_START(cap)
364 #define dtraceGcEnd(cap) \
365 HASKELLEVENT_GC_END(cap)
366 #define dtraceRequestSeqGc(cap) \
367 HASKELLEVENT_REQUEST_SEQ_GC(cap)
368 #define dtraceRequestParGc(cap) \
369 HASKELLEVENT_REQUEST_PAR_GC(cap)
370 #define dtraceCreateSparkThread(cap, spark_tid) \
371 HASKELLEVENT_CREATE_SPARK_THREAD(cap, spark_tid)
372 #define dtraceThreadLabel(cap, tso, label) \
373 HASKELLEVENT_THREAD_LABEL(cap, tso, label)
374 #define dtraceCapCreate(cap) \
375 HASKELLEVENT_CAP_CREATE(cap)
376 #define dtraceCapDelete(cap) \
377 HASKELLEVENT_CAP_DELETE(cap)
378 #define dtraceCapEnable(cap) \
379 HASKELLEVENT_CAP_ENABLE(cap)
380 #define dtraceCapDisable(cap) \
381 HASKELLEVENT_CAP_DISABLE(cap)
382 #define dtraceUserMsg(cap, msg) \
383 HASKELLEVENT_USER_MSG(cap, msg)
384 #define dtraceUserMarker(cap, msg) \
385 HASKELLEVENT_USER_MARKER(cap, msg)
386 #define dtraceGcIdle(cap) \
387 HASKELLEVENT_GC_IDLE(cap)
388 #define dtraceGcWork(cap) \
389 HASKELLEVENT_GC_WORK(cap)
390 #define dtraceGcDone(cap) \
391 HASKELLEVENT_GC_DONE(cap)
392 #define dtraceGcGlobalSync(cap) \
393 HASKELLEVENT_GC_GLOBAL_SYNC(cap)
394 #define dtraceEventGcStats(heap_capset, gens, \
395 copies, slop, fragmentation, \
396 par_n_threads, \
397 par_max_copied, \
398 par_tot_copied) \
399 HASKELLEVENT_GC_STATS(heap_capset, gens, \
400 copies, slop, fragmentation, \
401 par_n_threads, \
402 par_max_copied, \
403 par_tot_copied)
404 #define dtraceHeapInfo(heap_capset, gens, \
405 maxHeapSize, allocAreaSize, \
406 mblockSize, blockSize) \
407 HASKELLEVENT_HEAP_INFO(heap_capset, gens, \
408 maxHeapSize, allocAreaSize, \
409 mblockSize, blockSize)
410 #define dtraceEventHeapAllocated(cap, heap_capset, \
411 allocated) \
412 HASKELLEVENT_HEAP_ALLOCATED(cap, heap_capset, \
413 allocated)
414 #define dtraceEventHeapSize(heap_capset, size) \
415 HASKELLEVENT_HEAP_SIZE(heap_capset, size)
416 #define dtraceEventHeapLive(heap_capset, live) \
417 HASKELLEVENT_HEAP_LIVE(heap_capset, live)
418 #define dtraceCapsetCreate(capset, capset_type) \
419 HASKELLEVENT_CAPSET_CREATE(capset, capset_type)
420 #define dtraceCapsetDelete(capset) \
421 HASKELLEVENT_CAPSET_DELETE(capset)
422 #define dtraceCapsetAssignCap(capset, capno) \
423 HASKELLEVENT_CAPSET_ASSIGN_CAP(capset, capno)
424 #define dtraceCapsetRemoveCap(capset, capno) \
425 HASKELLEVENT_CAPSET_REMOVE_CAP(capset, capno)
426 #define dtraceSparkCounters(cap, a, b, c, d, e, f, g) \
427 HASKELLEVENT_SPARK_COUNTERS(cap, a, b, c, d, e, f, g)
428 #define dtraceSparkCreate(cap) \
429 HASKELLEVENT_SPARK_CREATE(cap)
430 #define dtraceSparkDud(cap) \
431 HASKELLEVENT_SPARK_DUD(cap)
432 #define dtraceSparkOverflow(cap) \
433 HASKELLEVENT_SPARK_OVERFLOW(cap)
434 #define dtraceSparkRun(cap) \
435 HASKELLEVENT_SPARK_RUN(cap)
436 #define dtraceSparkSteal(cap, victim_cap) \
437 HASKELLEVENT_SPARK_STEAL(cap, victim_cap)
438 #define dtraceSparkFizzle(cap) \
439 HASKELLEVENT_SPARK_FIZZLE(cap)
440 #define dtraceSparkGc(cap) \
441 HASKELLEVENT_SPARK_GC(cap)
442 #define dtraceTaskCreate(taskID, cap, tid) \
443 HASKELLEVENT_TASK_CREATE(taskID, cap, tid)
444 #define dtraceTaskMigrate(taskID, cap, new_cap) \
445 HASKELLEVENT_TASK_MIGRATE(taskID, cap, new_cap)
446 #define dtraceTaskDelete(taskID) \
447 HASKELLEVENT_TASK_DELETE(taskID)
448
449 #else /* !defined(DTRACE) */
450
451 #define dtraceCreateThread(cap, tid) /* nothing */
452 #define dtraceRunThread(cap, tid) /* nothing */
453 #define dtraceStopThread(cap, tid, status, info) /* nothing */
454 #define dtraceThreadRunnable(cap, tid) /* nothing */
455 #define dtraceMigrateThread(cap, tid, new_cap) /* nothing */
456 #define dtraceThreadWakeup(cap, tid, other_cap) /* nothing */
457 #define dtraceGcStart(cap) /* nothing */
458 #define dtraceGcEnd(cap) /* nothing */
459 #define dtraceRequestSeqGc(cap) /* nothing */
460 #define dtraceRequestParGc(cap) /* nothing */
461 #define dtraceCreateSparkThread(cap, spark_tid) /* nothing */
462 #define dtraceThreadLabel(cap, tso, label) /* nothing */
463 #define dtraceUserMsg(cap, msg) /* nothing */
464 #define dtraceUserMarker(cap, msg) /* nothing */
465 #define dtraceGcIdle(cap) /* nothing */
466 #define dtraceGcWork(cap) /* nothing */
467 #define dtraceGcDone(cap) /* nothing */
468 #define dtraceGcGlobalSync(cap) /* nothing */
469 #define dtraceEventGcStats(heap_capset, gens, \
470 copies, slop, fragmentation, \
471 par_n_threads, \
472 par_max_copied, \
473 par_tot_copied) /* nothing */
474 #define dtraceHeapInfo(heap_capset, gens, \
475 maxHeapSize, allocAreaSize, \
476 mblockSize, blockSize) /* nothing */
477 #define dtraceEventHeapAllocated(cap, heap_capset, \
478 allocated) /* nothing */
479 #define dtraceEventHeapSize(heap_capset, size) /* nothing */
480 #define dtraceEventHeapLive(heap_capset, live) /* nothing */
481 #define dtraceCapCreate(cap) /* nothing */
482 #define dtraceCapDelete(cap) /* nothing */
483 #define dtraceCapEnable(cap) /* nothing */
484 #define dtraceCapDisable(cap) /* nothing */
485 #define dtraceCapsetCreate(capset, capset_type) /* nothing */
486 #define dtraceCapsetDelete(capset) /* nothing */
487 #define dtraceCapsetAssignCap(capset, capno) /* nothing */
488 #define dtraceCapsetRemoveCap(capset, capno) /* nothing */
489 #define dtraceSparkCounters(cap, a, b, c, d, e, f, g) /* nothing */
490 #define dtraceSparkCreate(cap) /* nothing */
491 #define dtraceSparkDud(cap) /* nothing */
492 #define dtraceSparkOverflow(cap) /* nothing */
493 #define dtraceSparkRun(cap) /* nothing */
494 #define dtraceSparkSteal(cap, victim_cap) /* nothing */
495 #define dtraceSparkFizzle(cap) /* nothing */
496 #define dtraceSparkGc(cap) /* nothing */
497 #define dtraceTaskCreate(taskID, cap, tid) /* nothing */
498 #define dtraceTaskMigrate(taskID, cap, new_cap) /* nothing */
499 #define dtraceTaskDelete(taskID) /* nothing */
500
501 #endif
502
503 // -----------------------------------------------------------------------------
504 // Trace probes dispatching to various tracing frameworks
505 //
506 // In order to avoid accumulating multiple calls to tracing calls at trace
507 // points, we define inline probe functions that contain the various
508 // invocations.
509 //
510 // Dtrace - dtrace probes are unconditionally added as probe activation is
511 // handled by the dtrace component of the kernel, and inactive probes are
512 // very cheap - usually, one no-op. Consequently, dtrace can be used with
513 // all flavours of the RTS. In addition, we still support logging events to
514 // a file, even in the presence of dtrace. This is, eg, useful when tracing
515 // on a server, but browsing trace information with ThreadScope on a local
516 // client.
517 //
518 // -----------------------------------------------------------------------------
519
520 INLINE_HEADER void traceEventCreateThread(Capability *cap STG_UNUSED,
521 StgTSO *tso STG_UNUSED)
522 {
523 traceSchedEvent(cap, EVENT_CREATE_THREAD, tso, tso->stackobj->stack_size);
524 dtraceCreateThread((EventCapNo)cap->no, (EventThreadID)tso->id);
525 }
526
527 INLINE_HEADER void traceEventRunThread(Capability *cap STG_UNUSED,
528 StgTSO *tso STG_UNUSED)
529 {
530 traceSchedEvent(cap, EVENT_RUN_THREAD, tso, tso->what_next);
531 dtraceRunThread((EventCapNo)cap->no, (EventThreadID)tso->id);
532 }
533
534 INLINE_HEADER void traceEventStopThread(Capability *cap STG_UNUSED,
535 StgTSO *tso STG_UNUSED,
536 StgThreadReturnCode status STG_UNUSED,
537 StgWord32 info STG_UNUSED)
538 {
539 traceSchedEvent2(cap, EVENT_STOP_THREAD, tso, status, info);
540 dtraceStopThread((EventCapNo)cap->no, (EventThreadID)tso->id,
541 (EventThreadStatus)status, (EventThreadID)info);
542 }
543
544 INLINE_HEADER void traceEventMigrateThread(Capability *cap STG_UNUSED,
545 StgTSO *tso STG_UNUSED,
546 uint32_t new_cap STG_UNUSED)
547 {
548 traceSchedEvent(cap, EVENT_MIGRATE_THREAD, tso, new_cap);
549 dtraceMigrateThread((EventCapNo)cap->no, (EventThreadID)tso->id,
550 (EventCapNo)new_cap);
551 }
552
553 INLINE_HEADER void traceCapCreate(Capability *cap STG_UNUSED)
554 {
555 traceCapEvent(cap, EVENT_CAP_CREATE);
556 dtraceCapCreate((EventCapNo)cap->no);
557 }
558
559 INLINE_HEADER void traceCapDelete(Capability *cap STG_UNUSED)
560 {
561 traceCapEvent(cap, EVENT_CAP_DELETE);
562 dtraceCapDelete((EventCapNo)cap->no);
563 }
564
565 INLINE_HEADER void traceCapEnable(Capability *cap STG_UNUSED)
566 {
567 traceCapEvent(cap, EVENT_CAP_ENABLE);
568 dtraceCapEnable((EventCapNo)cap->no);
569 }
570
571 INLINE_HEADER void traceCapDisable(Capability *cap STG_UNUSED)
572 {
573 traceCapEvent(cap, EVENT_CAP_DISABLE);
574 dtraceCapDisable((EventCapNo)cap->no);
575 }
576
577 INLINE_HEADER void traceEventThreadWakeup(Capability *cap STG_UNUSED,
578 StgTSO *tso STG_UNUSED,
579 uint32_t other_cap STG_UNUSED)
580 {
581 traceSchedEvent(cap, EVENT_THREAD_WAKEUP, tso, other_cap);
582 dtraceThreadWakeup((EventCapNo)cap->no, (EventThreadID)tso->id,
583 (EventCapNo)other_cap);
584 }
585
586 INLINE_HEADER void traceThreadLabel(Capability *cap STG_UNUSED,
587 StgTSO *tso STG_UNUSED,
588 char *label STG_UNUSED)
589 {
590 if (RTS_UNLIKELY(TRACE_sched)) {
591 traceThreadLabel_(cap, tso, label);
592 }
593 dtraceThreadLabel((EventCapNo)cap->no, (EventThreadID)tso->id, label);
594 }
595
596 INLINE_HEADER void traceEventGcStart(Capability *cap STG_UNUSED)
597 {
598 traceGcEvent(cap, EVENT_GC_START);
599 dtraceGcStart((EventCapNo)cap->no);
600 }
601
602 INLINE_HEADER void traceEventGcStartAtT(Capability *cap STG_UNUSED,
603 StgWord64 ts STG_UNUSED)
604 {
605 traceGcEventAtT(cap, ts, EVENT_GC_START);
606 dtraceGcStart((EventCapNo)cap->no);
607 }
608
609 INLINE_HEADER void traceEventGcEnd(Capability *cap STG_UNUSED)
610 {
611 traceGcEvent(cap, EVENT_GC_END);
612 dtraceGcEnd((EventCapNo)cap->no);
613 }
614
615 INLINE_HEADER void traceEventGcEndAtT(Capability *cap STG_UNUSED,
616 StgWord64 ts STG_UNUSED)
617 {
618 traceGcEventAtT(cap, ts, EVENT_GC_END);
619 dtraceGcEnd((EventCapNo)cap->no);
620 }
621
622 INLINE_HEADER void traceEventRequestSeqGc(Capability *cap STG_UNUSED)
623 {
624 traceGcEvent(cap, EVENT_REQUEST_SEQ_GC);
625 dtraceRequestSeqGc((EventCapNo)cap->no);
626 }
627
628 INLINE_HEADER void traceEventRequestParGc(Capability *cap STG_UNUSED)
629 {
630 traceGcEvent(cap, EVENT_REQUEST_PAR_GC);
631 dtraceRequestParGc((EventCapNo)cap->no);
632 }
633
634 INLINE_HEADER void traceEventGcIdle(Capability *cap STG_UNUSED)
635 {
636 traceGcEvent(cap, EVENT_GC_IDLE);
637 dtraceGcIdle((EventCapNo)cap->no);
638 }
639
640 INLINE_HEADER void traceEventGcWork(Capability *cap STG_UNUSED)
641 {
642 traceGcEvent(cap, EVENT_GC_WORK);
643 dtraceGcWork((EventCapNo)cap->no);
644 }
645
646 INLINE_HEADER void traceEventGcDone(Capability *cap STG_UNUSED)
647 {
648 traceGcEvent(cap, EVENT_GC_DONE);
649 dtraceGcDone((EventCapNo)cap->no);
650 }
651
652 INLINE_HEADER void traceEventGcGlobalSync(Capability *cap STG_UNUSED)
653 {
654 traceGcEvent(cap, EVENT_GC_GLOBAL_SYNC);
655 dtraceGcGlobalSync((EventCapNo)cap->no);
656 }
657
658 INLINE_HEADER void traceEventGcStats(Capability *cap STG_UNUSED,
659 CapsetID heap_capset STG_UNUSED,
660 uint32_t gen STG_UNUSED,
661 W_ copied STG_UNUSED,
662 W_ slop STG_UNUSED,
663 W_ fragmentation STG_UNUSED,
664 uint32_t par_n_threads STG_UNUSED,
665 W_ par_max_copied STG_UNUSED,
666 W_ par_tot_copied STG_UNUSED)
667 {
668 if (RTS_UNLIKELY(TRACE_gc)) {
669 traceEventGcStats_(cap, heap_capset, gen,
670 copied, slop, fragmentation,
671 par_n_threads, par_max_copied, par_tot_copied);
672 }
673 dtraceEventGcStats(heap_capset, gen,
674 copied, slop, fragmentation,
675 par_n_threads, par_max_copied, par_tot_copied);
676 }
677
678 INLINE_HEADER void traceEventHeapInfo(CapsetID heap_capset STG_UNUSED,
679 uint32_t gens STG_UNUSED,
680 W_ maxHeapSize STG_UNUSED,
681 W_ allocAreaSize STG_UNUSED,
682 W_ mblockSize STG_UNUSED,
683 W_ blockSize STG_UNUSED)
684 {
685 if (RTS_UNLIKELY(TRACE_gc)) {
686 traceEventHeapInfo_(heap_capset, gens,
687 maxHeapSize, allocAreaSize,
688 mblockSize, blockSize);
689 }
690 dtraceHeapInfo(heap_capset, gens,
691 maxHeapSize, allocAreaSize,
692 mblockSize, blockSize);
693 }
694
695 INLINE_HEADER void traceEventHeapAllocated(Capability *cap STG_UNUSED,
696 CapsetID heap_capset STG_UNUSED,
697 W_ allocated STG_UNUSED)
698 {
699 traceHeapEvent(cap, EVENT_HEAP_ALLOCATED, heap_capset, allocated);
700 dtraceEventHeapAllocated((EventCapNo)cap->no, heap_capset, allocated);
701 }
702
703 INLINE_HEADER void traceEventHeapSize(Capability *cap STG_UNUSED,
704 CapsetID heap_capset STG_UNUSED,
705 W_ heap_size STG_UNUSED)
706 {
707 traceHeapEvent(cap, EVENT_HEAP_SIZE, heap_capset, heap_size);
708 dtraceEventHeapSize(heap_capset, heap_size);
709 }
710
711 INLINE_HEADER void traceEventHeapLive(Capability *cap STG_UNUSED,
712 CapsetID heap_capset STG_UNUSED,
713 W_ heap_live STG_UNUSED)
714 {
715 traceHeapEvent(cap, EVENT_HEAP_LIVE, heap_capset, heap_live);
716 dtraceEventHeapLive(heap_capset, heap_live);
717 }
718
719 INLINE_HEADER void traceCapsetCreate(CapsetID capset STG_UNUSED,
720 CapsetType capset_type STG_UNUSED)
721 {
722 traceCapsetEvent(EVENT_CAPSET_CREATE, capset, capset_type);
723 dtraceCapsetCreate(capset, capset_type);
724 }
725
726 INLINE_HEADER void traceCapsetDelete(CapsetID capset STG_UNUSED)
727 {
728 traceCapsetEvent(EVENT_CAPSET_DELETE, capset, 0);
729 dtraceCapsetDelete(capset);
730 }
731
732 INLINE_HEADER void traceCapsetAssignCap(CapsetID capset STG_UNUSED,
733 uint32_t capno STG_UNUSED)
734 {
735 traceCapsetEvent(EVENT_CAPSET_ASSIGN_CAP, capset, capno);
736 dtraceCapsetAssignCap(capset, capno);
737 }
738
739 INLINE_HEADER void traceCapsetRemoveCap(CapsetID capset STG_UNUSED,
740 uint32_t capno STG_UNUSED)
741 {
742 traceCapsetEvent(EVENT_CAPSET_REMOVE_CAP, capset, capno);
743 dtraceCapsetRemoveCap(capset, capno);
744 }
745
746 INLINE_HEADER void traceWallClockTime(void)
747 {
748 traceWallClockTime_();
749 /* Note: no DTrace equivalent because it is available to DTrace directly */
750 }
751
752 INLINE_HEADER void traceOSProcessInfo(void)
753 {
754 traceOSProcessInfo_();
755 /* Note: no DTrace equivalent because all this OS process info
756 * is available to DTrace directly */
757 }
758
759 INLINE_HEADER void traceEventCreateSparkThread(Capability *cap STG_UNUSED,
760 StgThreadID spark_tid STG_UNUSED)
761 {
762 traceSparkEvent2(cap, EVENT_CREATE_SPARK_THREAD, spark_tid);
763 dtraceCreateSparkThread((EventCapNo)cap->no, (EventThreadID)spark_tid);
764 }
765
766 INLINE_HEADER void traceSparkCounters(Capability *cap STG_UNUSED)
767 {
768 #ifdef THREADED_RTS
769 if (RTS_UNLIKELY(TRACE_spark_sampled)) {
770 traceSparkCounters_(cap, cap->spark_stats, sparkPoolSize(cap->sparks));
771 }
772 dtraceSparkCounters((EventCapNo)cap->no,
773 cap->spark_stats.created,
774 cap->spark_stats.dud,
775 cap->spark_stats.overflowed,
776 cap->spark_stats.converted,
777 cap->spark_stats.gcd,
778 cap->spark_stats.fizzled,
779 sparkPoolSize(cap->sparks));
780 #endif
781 }
782
783 INLINE_HEADER void traceEventSparkCreate(Capability *cap STG_UNUSED)
784 {
785 traceSparkEvent(cap, EVENT_SPARK_CREATE);
786 dtraceSparkCreate((EventCapNo)cap->no);
787 }
788
789 INLINE_HEADER void traceEventSparkDud(Capability *cap STG_UNUSED)
790 {
791 traceSparkEvent(cap, EVENT_SPARK_DUD);
792 dtraceSparkDud((EventCapNo)cap->no);
793 }
794
795 INLINE_HEADER void traceEventSparkOverflow(Capability *cap STG_UNUSED)
796 {
797 traceSparkEvent(cap, EVENT_SPARK_OVERFLOW);
798 dtraceSparkOverflow((EventCapNo)cap->no);
799 }
800
801 INLINE_HEADER void traceEventSparkRun(Capability *cap STG_UNUSED)
802 {
803 traceSparkEvent(cap, EVENT_SPARK_RUN);
804 dtraceSparkRun((EventCapNo)cap->no);
805 }
806
807 INLINE_HEADER void traceEventSparkSteal(Capability *cap STG_UNUSED,
808 uint32_t victim_cap STG_UNUSED)
809 {
810 traceSparkEvent2(cap, EVENT_SPARK_STEAL, victim_cap);
811 dtraceSparkSteal((EventCapNo)cap->no, (EventCapNo)victim_cap);
812 }
813
814 INLINE_HEADER void traceEventSparkFizzle(Capability *cap STG_UNUSED)
815 {
816 traceSparkEvent(cap, EVENT_SPARK_FIZZLE);
817 dtraceSparkFizzle((EventCapNo)cap->no);
818 }
819
820 INLINE_HEADER void traceEventSparkGC(Capability *cap STG_UNUSED)
821 {
822 traceSparkEvent(cap, EVENT_SPARK_GC);
823 dtraceSparkGc((EventCapNo)cap->no);
824 }
825
826 INLINE_HEADER void traceTaskCreate(Task *task STG_UNUSED,
827 Capability *cap STG_UNUSED)
828 {
829 ASSERT(task->cap == cap);
830 // TODO: asserting task->cap == NULL would be much stronger
831 // (the intention being that the task structure is just created and empty)
832 // but would require large changes of traceTaskCreate calls.
833 ASSERT(cap != NULL);
834 // A new task gets associated with a cap. We also record
835 // the kernel thread id of the task, which should never change.
836 if (RTS_UNLIKELY(TRACE_sched)) {
837 traceTaskCreate_(task, cap);
838 }
839 dtraceTaskCreate(serialisableTaskId(task),
840 (EventCapNo)cap->no,
841 kernelThreadId());
842 }
843
844 INLINE_HEADER void traceTaskMigrate(Task *task STG_UNUSED,
845 Capability *cap STG_UNUSED,
846 Capability *new_cap STG_UNUSED)
847 {
848 ASSERT(task->cap == cap);
849 ASSERT(cap != NULL);
850 ASSERT(cap != new_cap);
851 ASSERT(new_cap != NULL);
852 // A task migrates from a cap to another.
853 if (RTS_UNLIKELY(TRACE_sched)) {
854 traceTaskMigrate_(task, cap, new_cap);
855 }
856 dtraceTaskMigrate(serialisableTaskId(task), (EventCapNo)cap->no,
857 (EventCapNo)new_cap->no);
858 }
859
860 INLINE_HEADER void traceTaskDelete(Task *task STG_UNUSED)
861 {
862 ASSERT(task->cap != NULL);
863 if (RTS_UNLIKELY(TRACE_sched)) {
864 traceTaskDelete_(task);
865 }
866 dtraceTaskDelete(serialisableTaskId(task));
867 }
868
869 #include "EndPrivate.h"
870
871 #endif /* TRACE_H */