Trace.c 23.2 KB
Newer Older
Simon Marlow's avatar
Simon Marlow committed
1 2
/* -----------------------------------------------------------------------------
 *
Simon Marlow's avatar
Simon Marlow committed
3
 * (c) The GHC Team 2006-2009
Simon Marlow's avatar
Simon Marlow committed
4 5 6 7 8
 *
 * Debug and performance tracing
 *
 * ---------------------------------------------------------------------------*/

Simon Marlow's avatar
Simon Marlow committed
9
// external headers
Simon Marlow's avatar
Simon Marlow committed
10
#include "Rts.h"
11

Simon Marlow's avatar
Simon Marlow committed
12
// internal headers
Simon Marlow's avatar
Simon Marlow committed
13
#include "Trace.h"
14

Ben Gamari's avatar
Ben Gamari committed
15
#if defined(TRACING)
16

Simon Marlow's avatar
Simon Marlow committed
17
#include "GetTime.h"
18
#include "GetEnv.h"
Simon Marlow's avatar
Simon Marlow committed
19
#include "Stats.h"
20
#include "eventlog/EventLog.h"
21
#include "rts/EventLogWriter.h"
22 23
#include "Threads.h"
#include "Printer.h"
24
#include "RtsFlags.h"
Simon Marlow's avatar
Simon Marlow committed
25

Ben Gamari's avatar
Ben Gamari committed
26
#if defined(HAVE_UNISTD_H)
27 28 29
#include <unistd.h>
#endif

30 31
// events
int TRACE_sched;
32
int TRACE_gc;
33 34
int TRACE_spark_sampled;
int TRACE_spark_full;
35
int TRACE_user;
36
int TRACE_cap;
Simon Marlow's avatar
Simon Marlow committed
37

Ben Gamari's avatar
Ben Gamari committed
38
#if defined(THREADED_RTS)
Simon Marlow's avatar
Simon Marlow committed
39 40 41
static Mutex trace_utx;
#endif

Ben Gamari's avatar
Ben Gamari committed
42
static bool eventlog_enabled;
43

44
/* ---------------------------------------------------------------------------
Gabor Greif's avatar
Gabor Greif committed
45
   Starting up / shutting down the tracing facilities
46
 --------------------------------------------------------------------------- */
Simon Marlow's avatar
Simon Marlow committed
47

48 49 50 51 52
static const EventLogWriter *getEventLogWriter(void)
{
    return rtsConfig.eventlog_writer;
}

Simon Marlow's avatar
Simon Marlow committed
53 54
void initTracing (void)
{
55 56
    const EventLogWriter *eventlog_writer = getEventLogWriter();

Ben Gamari's avatar
Ben Gamari committed
57
#if defined(THREADED_RTS)
Simon Marlow's avatar
Simon Marlow committed
58 59 60
    initMutex(&trace_utx);
#endif

61 62 63 64 65
    // -Ds turns on scheduler tracing too
    TRACE_sched =
        RtsFlags.TraceFlags.scheduler ||
        RtsFlags.DebugFlags.scheduler;

66 67 68
    // -Dg turns on gc tracing too
    TRACE_gc =
        RtsFlags.TraceFlags.gc ||
69 70
        RtsFlags.DebugFlags.gc ||
        RtsFlags.DebugFlags.scheduler;
71 72 73
    if (TRACE_gc && RtsFlags.GcFlags.giveStats == NO_GC_STATS) {
        RtsFlags.GcFlags.giveStats = COLLECT_GC_STATS;
    }
74

75 76 77 78 79 80
    TRACE_spark_sampled =
        RtsFlags.TraceFlags.sparks_sampled;

    // -Dr turns on full spark tracing
    TRACE_spark_full =
        RtsFlags.TraceFlags.sparks_full ||
81 82
        RtsFlags.DebugFlags.sparks;

83 84 85
    TRACE_user =
        RtsFlags.TraceFlags.user;

86 87 88 89 90 91 92 93
    // We trace cap events if we're tracing anything else
    TRACE_cap =
        TRACE_sched ||
        TRACE_gc ||
        TRACE_spark_sampled ||
        TRACE_spark_full ||
        TRACE_user;

94 95
    eventlog_enabled = RtsFlags.TraceFlags.tracing == TRACE_EVENTLOG &&
                        eventlog_writer != NULL;
96

97
    /* Note: we can have any of the TRACE_* flags turned on even when
98 99 100
       eventlog_enabled is off. In the DEBUG way we may be tracing to stderr.
     */

101
    if (eventlog_enabled) {
102
        initEventLogging(eventlog_writer);
103
    }
104 105 106 107
}

void endTracing (void)
{
108 109 110
    if (eventlog_enabled) {
        endEventLogging();
    }
111 112 113 114
}

void freeTracing (void)
{
115 116 117
    if (eventlog_enabled) {
        freeEventLogging();
    }
Simon Marlow's avatar
Simon Marlow committed
118 119
}

120 121
void resetTracing (void)
{
122 123 124
    const EventLogWriter *eventlog_writer;
    eventlog_writer = getEventLogWriter();

125 126
    if (eventlog_enabled) {
        abortEventLogging(); // abort eventlog inherited from parent
127 128 129
        if (eventlog_writer != NULL) {
            initEventLogging(eventlog_writer); // child starts its own eventlog
        }
130 131 132
    }
}

133 134 135 136 137 138 139
void flushTrace (void)
{
    if (eventlog_enabled) {
        flushEventLog();
    }
}

140
void tracingAddCapapilities (uint32_t from, uint32_t to)
141 142 143 144 145 146
{
    if (eventlog_enabled) {
        moreCapEventBufs(from,to);
    }
}

147 148 149 150
/* ---------------------------------------------------------------------------
   Emitting trace messages/events
 --------------------------------------------------------------------------- */

Ben Gamari's avatar
Ben Gamari committed
151
#if defined(DEBUG)
Simon Marlow's avatar
Simon Marlow committed
152 153
static void tracePreface (void)
{
Ben Gamari's avatar
Ben Gamari committed
154
#if defined(THREADED_RTS)
Simon Marlow's avatar
Simon Marlow committed
155 156
    debugBelch("%12lx: ", (unsigned long)osThreadId());
#endif
157
    if (RtsFlags.TraceFlags.timestamp) {
158
        debugBelch("%9" FMT_Word64 ": ", stat_getElapsedTime());
Simon Marlow's avatar
Simon Marlow committed
159 160
    }
}
161 162
#endif

Ben Gamari's avatar
Ben Gamari committed
163
#if defined(DEBUG)
164 165 166 167 168 169
static char *thread_stop_reasons[] = {
    [HeapOverflow] = "heap overflow",
    [StackOverflow] = "stack overflow",
    [ThreadYielding] = "yielding",
    [ThreadBlocked] = "blocked",
    [ThreadFinished] = "finished",
170 171
    [THREAD_SUSPENDED_FOREIGN_CALL] = "suspended while making a foreign call",
    [6 + BlockedOnMVar]         = "blocked on an MVar",
172
    [6 + BlockedOnMVarRead]     = "blocked on an atomic MVar read",
173 174 175 176 177 178 179 180 181 182
    [6 + BlockedOnBlackHole]    = "blocked on a black hole",
    [6 + BlockedOnRead]         = "blocked on a read operation",
    [6 + BlockedOnWrite]        = "blocked on a write operation",
    [6 + BlockedOnDelay]        = "blocked on a delay operation",
    [6 + BlockedOnSTM]          = "blocked on STM",
    [6 + BlockedOnDoProc]       = "blocked on asyncDoProc",
    [6 + BlockedOnCCall]        = "blocked on a foreign call",
    [6 + BlockedOnCCall_Interruptible] = "blocked on a foreign call (interruptible)",
    [6 + BlockedOnMsgThrowTo]   =  "blocked on throwTo",
    [6 + ThreadMigrating]       =  "migrating"
183 184
};
#endif
Simon Marlow's avatar
Simon Marlow committed
185

Ben Gamari's avatar
Ben Gamari committed
186
#if defined(DEBUG)
187 188
static void traceSchedEvent_stderr (Capability *cap, EventTypeNum tag,
                                    StgTSO *tso,
189 190
                                    StgWord info1 STG_UNUSED,
                                    StgWord info2 STG_UNUSED)
Simon Marlow's avatar
Simon Marlow committed
191
{
192 193 194 195 196
    ACQUIRE_LOCK(&trace_utx);

    tracePreface();
    switch (tag) {
    case EVENT_CREATE_THREAD:   // (cap, thread)
197
        debugBelch("cap %d: created thread %" FMT_Word "\n",
198
                   cap->no, (W_)tso->id);
199 200
        break;
    case EVENT_RUN_THREAD:      //  (cap, thread)
201
        debugBelch("cap %d: running thread %" FMT_Word " (%s)\n",
202
                   cap->no, (W_)tso->id, what_next_strs[tso->what_next]);
203 204
        break;
    case EVENT_THREAD_RUNNABLE: // (cap, thread)
205
        debugBelch("cap %d: thread %" FMT_Word " appended to run queue\n",
206
                   cap->no, (W_)tso->id);
207 208
        break;
    case EVENT_MIGRATE_THREAD:  // (cap, thread, new_cap)
209
        debugBelch("cap %d: thread %" FMT_Word " migrating to cap %d\n",
210
                   cap->no, (W_)tso->id, (int)info1);
211
        break;
212
    case EVENT_THREAD_WAKEUP:   // (cap, thread, info1_cap)
213
        debugBelch("cap %d: waking up thread %" FMT_Word " on cap %d\n",
214
                   cap->no, (W_)tso->id, (int)info1);
215
        break;
216

217
    case EVENT_STOP_THREAD:     // (cap, thread, status)
218
        if (info1 == 6 + BlockedOnBlackHole) {
Ian Lynagh's avatar
Ian Lynagh committed
219
            debugBelch("cap %d: thread %" FMT_Word " stopped (blocked on black hole owned by thread %lu)\n",
220
                       cap->no, (W_)tso->id, (long)info2);
221
        } else {
Ian Lynagh's avatar
Ian Lynagh committed
222
            debugBelch("cap %d: thread %" FMT_Word " stopped (%s)\n",
223
                       cap->no, (W_)tso->id, thread_stop_reasons[info1]);
224
        }
225 226
        break;
    default:
227
        debugBelch("cap %d: thread %" FMT_Word ": event %d\n\n",
228
                   cap->no, (W_)tso->id, tag);
229 230 231 232 233 234
        break;
    }

    RELEASE_LOCK(&trace_utx);
}
#endif
Simon Marlow's avatar
Simon Marlow committed
235

236
void traceSchedEvent_ (Capability *cap, EventTypeNum tag,
237
                       StgTSO *tso, StgWord info1, StgWord info2)
238
{
Ben Gamari's avatar
Ben Gamari committed
239
#if defined(DEBUG)
240
    if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
241
        traceSchedEvent_stderr(cap, tag, tso, info1, info2);
242 243 244
    } else
#endif
    {
245
        postSchedEvent(cap,tag,tso ? tso->id : 0, info1, info2);
246 247 248
    }
}

Ben Gamari's avatar
Ben Gamari committed
249
#if defined(DEBUG)
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
static void traceGcEvent_stderr (Capability *cap, EventTypeNum tag)
{
    ACQUIRE_LOCK(&trace_utx);

    tracePreface();
    switch (tag) {
      case EVENT_REQUEST_SEQ_GC:  // (cap)
          debugBelch("cap %d: requesting sequential GC\n", cap->no);
          break;
      case EVENT_REQUEST_PAR_GC:  // (cap)
          debugBelch("cap %d: requesting parallel GC\n", cap->no);
          break;
      case EVENT_GC_START:        // (cap)
          debugBelch("cap %d: starting GC\n", cap->no);
          break;
      case EVENT_GC_END:          // (cap)
          debugBelch("cap %d: finished GC\n", cap->no);
          break;
      case EVENT_GC_IDLE:         // (cap)
          debugBelch("cap %d: GC idle\n", cap->no);
          break;
      case EVENT_GC_WORK:         // (cap)
          debugBelch("cap %d: GC working\n", cap->no);
          break;
      case EVENT_GC_DONE:         // (cap)
          debugBelch("cap %d: GC done\n", cap->no);
          break;
277 278 279
      case EVENT_GC_GLOBAL_SYNC:  // (cap)
          debugBelch("cap %d: all caps stopped for GC\n", cap->no);
          break;
280 281 282 283 284 285 286 287 288 289 290
      default:
          barf("traceGcEvent: unknown event tag %d", tag);
          break;
    }

    RELEASE_LOCK(&trace_utx);
}
#endif

void traceGcEvent_ (Capability *cap, EventTypeNum tag)
{
Ben Gamari's avatar
Ben Gamari committed
291
#if defined(DEBUG)
292 293 294 295 296 297 298 299 300 301
    if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
        traceGcEvent_stderr(cap, tag);
    } else
#endif
    {
        /* currently all GC events are nullary events */
        postEvent(cap, tag);
    }
}

302 303
void traceGcEventAtT_ (Capability *cap, StgWord64 ts, EventTypeNum tag)
{
Ben Gamari's avatar
Ben Gamari committed
304
#if defined(DEBUG)
305 306 307 308 309 310 311 312 313 314
    if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
        traceGcEvent_stderr(cap, tag);
    } else
#endif
    {
        /* assuming nullary events and explicitly inserting a timestamp */
        postEventAtTimestamp(cap, ts, tag);
    }
}

315 316 317
void traceHeapEvent_ (Capability   *cap,
                      EventTypeNum  tag,
                      CapsetID      heap_capset,
318
                      W_          info1)
319
{
Ben Gamari's avatar
Ben Gamari committed
320
#if defined(DEBUG)
321 322 323 324 325 326 327
    if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
        /* no stderr equivalent for these ones */
    } else
#endif
    {
        postHeapEvent(cap, tag, heap_capset, info1);
    }
328 329 330
}

void traceEventHeapInfo_ (CapsetID    heap_capset,
331
                          uint32_t  gens,
332 333 334 335
                          W_        maxHeapSize,
                          W_        allocAreaSize,
                          W_        mblockSize,
                          W_        blockSize)
336
{
Ben Gamari's avatar
Ben Gamari committed
337
#if defined(DEBUG)
338 339 340 341 342 343 344 345 346
    if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
        /* no stderr equivalent for these ones */
    } else
#endif
    {
        postEventHeapInfo(heap_capset, gens,
                          maxHeapSize, allocAreaSize,
                          mblockSize, blockSize);
    }
347 348 349 350
}

void traceEventGcStats_  (Capability *cap,
                          CapsetID    heap_capset,
351
                          uint32_t  gen,
352 353 354
                          W_        copied,
                          W_        slop,
                          W_        fragmentation,
355
                          uint32_t  par_n_threads,
356
                          W_        par_max_copied,
357 358
                          W_        par_tot_copied,
                          W_        par_balanced_copied)
359
{
Ben Gamari's avatar
Ben Gamari committed
360
#if defined(DEBUG)
361 362 363 364 365 366 367
    if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
        /* no stderr equivalent for these ones */
    } else
#endif
    {
        postEventGcStats(cap, heap_capset, gen,
                         copied, slop, fragmentation,
368 369
                         par_n_threads, par_max_copied,
                         par_tot_copied, par_balanced_copied);
370
    }
371 372
}

373 374
void traceCapEvent_ (Capability   *cap,
                     EventTypeNum  tag)
375
{
Ben Gamari's avatar
Ben Gamari committed
376
#if defined(DEBUG)
377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404
    if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
        ACQUIRE_LOCK(&trace_utx);

        tracePreface();
        switch (tag) {
        case EVENT_CAP_CREATE:   // (cap)
            debugBelch("cap %d: initialised\n", cap->no);
            break;
        case EVENT_CAP_DELETE:   // (cap)
            debugBelch("cap %d: shutting down\n", cap->no);
            break;
        case EVENT_CAP_ENABLE:   // (cap)
            debugBelch("cap %d: enabling capability\n", cap->no);
            break;
        case EVENT_CAP_DISABLE:  // (cap)
            debugBelch("cap %d: disabling capability\n", cap->no);
            break;
        }
        RELEASE_LOCK(&trace_utx);
    } else
#endif
    {
        if (eventlog_enabled) {
            postCapEvent(tag, (EventCapNo)cap->no);
        }
    }
}

405 406 407
void traceCapsetEvent_ (EventTypeNum tag,
                        CapsetID     capset,
                        StgWord      info)
408
{
Ben Gamari's avatar
Ben Gamari committed
409
#if defined(DEBUG)
410 411 412 413
    if (RtsFlags.TraceFlags.tracing == TRACE_STDERR && TRACE_sched)
        // When events go to stderr, it is annoying to see the capset
        // events every time, so we only emit them with -Ds.
    {
414 415 416 417 418
        ACQUIRE_LOCK(&trace_utx);

        tracePreface();
        switch (tag) {
        case EVENT_CAPSET_CREATE:   // (capset, capset_type)
419 420
            debugBelch("created capset %" FMT_Word32 " of type %d\n", capset,
                       (int)info);
421 422
            break;
        case EVENT_CAPSET_DELETE:   // (capset)
423
            debugBelch("deleted capset %" FMT_Word32 "\n", capset);
424 425
            break;
        case EVENT_CAPSET_ASSIGN_CAP:  // (capset, capno)
426 427
            debugBelch("assigned cap %" FMT_Word " to capset %" FMT_Word32 "\n",
                       info, capset);
428 429
            break;
        case EVENT_CAPSET_REMOVE_CAP:  // (capset, capno)
430 431
            debugBelch("removed cap %" FMT_Word " from capset %" FMT_Word32
                       "\n", info, capset);
432 433 434 435 436 437 438
            break;
        }
        RELEASE_LOCK(&trace_utx);
    } else
#endif
    {
        if (eventlog_enabled) {
439
            postCapsetEvent(tag, capset, info);
440 441 442 443
        }
    }
}

444 445 446 447 448 449
void traceWallClockTime_(void) {
    if (eventlog_enabled) {
        postWallClockTime(CAPSET_CLOCKDOMAIN_DEFAULT);
    }
}

450 451
void traceOSProcessInfo_(void) {
    if (eventlog_enabled) {
452 453 454
        postCapsetEvent(EVENT_OSPROCESS_PID,
                        CAPSET_OSPROCESS_DEFAULT,
                        getpid());
455

456
#if !defined (mingw32_HOST_OS)
Gabor Greif's avatar
Gabor Greif committed
457
/* Windows has no strong concept of process hierarchy, so no getppid().
458 459 460
 * In any case, this trace event is mainly useful for tracing programs
 * that use 'forkProcess' which Windows doesn't support anyway.
 */
461 462 463
        postCapsetEvent(EVENT_OSPROCESS_PPID,
                        CAPSET_OSPROCESS_DEFAULT,
                        getppid());
464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493
#endif
        {
            char buf[256];
            snprintf(buf, sizeof(buf), "GHC-%s %s", ProjectVersion, RtsWay);
            postCapsetStrEvent(EVENT_RTS_IDENTIFIER,
                               CAPSET_OSPROCESS_DEFAULT,
                               buf);
        }
        {
            int argc = 0; char **argv;
            getFullProgArgv(&argc, &argv);
            if (argc != 0) {
                postCapsetVecEvent(EVENT_PROGRAM_ARGS,
                                   CAPSET_OSPROCESS_DEFAULT,
                                   argc, argv);
            }
        }
        {
            int envc = 0; char **envv;
            getProgEnvv(&envc, &envv);
            if (envc != 0) {
                postCapsetVecEvent(EVENT_PROGRAM_ENV,
                                   CAPSET_OSPROCESS_DEFAULT,
                                   envc, envv);
            }
            freeProgEnvv(envc, envv);
        }
    }
}

Ben Gamari's avatar
Ben Gamari committed
494
#if defined(DEBUG)
495
static void traceSparkEvent_stderr (Capability *cap, EventTypeNum tag,
496 497 498 499 500 501 502 503
                                    StgWord info1)
{
    ACQUIRE_LOCK(&trace_utx);

    tracePreface();
    switch (tag) {

    case EVENT_CREATE_SPARK_THREAD: // (cap, spark_thread)
504
        debugBelch("cap %d: creating spark thread %lu\n",
505 506 507 508 509 510 511
                   cap->no, (long)info1);
        break;
    case EVENT_SPARK_CREATE:        // (cap)
        debugBelch("cap %d: added spark to pool\n",
                   cap->no);
        break;
    case EVENT_SPARK_DUD:           //  (cap)
512
        debugBelch("cap %d: discarded dud spark\n",
513 514 515
                   cap->no);
        break;
    case EVENT_SPARK_OVERFLOW:      // (cap)
516
        debugBelch("cap %d: discarded overflowed spark\n",
517 518 519
                   cap->no);
        break;
    case EVENT_SPARK_RUN:           // (cap)
520
        debugBelch("cap %d: running a spark\n",
521 522 523
                   cap->no);
        break;
    case EVENT_SPARK_STEAL:         // (cap, victim_cap)
524
        debugBelch("cap %d: stealing a spark from cap %d\n",
525 526 527
                   cap->no, (int)info1);
        break;
    case EVENT_SPARK_FIZZLE:        // (cap)
528
        debugBelch("cap %d: fizzled spark removed from pool\n",
529 530 531
                   cap->no);
        break;
    case EVENT_SPARK_GC:            // (cap)
532
        debugBelch("cap %d: GCd spark removed from pool\n",
533 534 535 536 537 538 539 540 541 542 543 544 545
                   cap->no);
        break;
    default:
        barf("traceSparkEvent: unknown event tag %d", tag);
        break;
    }

    RELEASE_LOCK(&trace_utx);
}
#endif

void traceSparkEvent_ (Capability *cap, EventTypeNum tag, StgWord info1)
{
Ben Gamari's avatar
Ben Gamari committed
546
#if defined(DEBUG)
547 548 549 550 551 552 553 554 555
    if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
        traceSparkEvent_stderr(cap, tag, info1);
    } else
#endif
    {
        postSparkEvent(cap,tag,info1);
    }
}

Duncan Coutts's avatar
Duncan Coutts committed
556 557 558 559
void traceSparkCounters_ (Capability *cap,
                          SparkCounters counters,
                          StgWord remaining)
{
Ben Gamari's avatar
Ben Gamari committed
560
#if defined(DEBUG)
Duncan Coutts's avatar
Duncan Coutts committed
561 562 563 564 565 566 567 568 569 570
    if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
        /* we currently don't do debug tracing of spark stats but we must
           test for TRACE_STDERR because of the !eventlog_enabled case. */
    } else
#endif
    {
        postSparkCountersEvent(cap, counters, remaining);
    }
}

571 572 573
void traceTaskCreate_ (Task       *task,
                       Capability *cap)
{
Ben Gamari's avatar
Ben Gamari committed
574
#if defined(DEBUG)
575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590
    if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
        /* We currently don't do debug tracing of tasks but we must
           test for TRACE_STDERR because of the !eventlog_enabled case. */
    } else
#endif
    {
        EventTaskId         taskid = serialisableTaskId(task);
        EventKernelThreadId tid    = kernelThreadId();
        postTaskCreateEvent(taskid, cap->no, tid);
    }
}

void traceTaskMigrate_ (Task       *task,
                        Capability *cap,
                        Capability *new_cap)
{
Ben Gamari's avatar
Ben Gamari committed
591
#if defined(DEBUG)
592 593 594 595 596 597 598 599 600 601 602 603 604
    if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
        /* We currently don't do debug tracing of tasks but we must
           test for TRACE_STDERR because of the !eventlog_enabled case. */
    } else
#endif
    {
        EventTaskId taskid = serialisableTaskId(task);
        postTaskMigrateEvent(taskid, cap->no, new_cap->no);
    }
}

void traceTaskDelete_ (Task *task)
{
Ben Gamari's avatar
Ben Gamari committed
605
#if defined(DEBUG)
606 607 608 609 610 611 612 613 614 615 616
    if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
        /* We currently don't do debug tracing of tasks but we must
           test for TRACE_STDERR because of the !eventlog_enabled case. */
    } else
#endif
    {
        EventTaskId taskid = serialisableTaskId(task);
        postTaskDeleteEvent(taskid);
    }
}

617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638
void traceHeapProfBegin(StgWord8 profile_id)
{
    if (eventlog_enabled) {
        postHeapProfBegin(profile_id);
    }
}

void traceHeapProfSampleBegin(StgInt era)
{
    if (eventlog_enabled) {
        postHeapProfSampleBegin(era);
    }
}

void traceHeapProfSampleString(StgWord8 profile_id,
                               const char *label, StgWord residency)
{
    if (eventlog_enabled) {
        postHeapProfSampleString(profile_id, label, residency);
    }
}

Ben Gamari's avatar
Ben Gamari committed
639
#if defined(PROFILING)
640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659
void traceHeapProfCostCentre(StgWord32 ccID,
                             const char *label,
                             const char *module,
                             const char *srcloc,
                             StgBool is_caf)
{
    if (eventlog_enabled) {
        postHeapProfCostCentre(ccID, label, module, srcloc, is_caf);
    }
}

void traceHeapProfSampleCostCentre(StgWord8 profile_id,
                                   CostCentreStack *stack, StgWord residency)
{
    if (eventlog_enabled) {
        postHeapProfSampleCostCentre(profile_id, stack, residency);
    }
}
#endif

Ben Gamari's avatar
Ben Gamari committed
660
#if defined(DEBUG)
661
static void vtraceCap_stderr(Capability *cap, char *msg, va_list ap)
662
{
Simon Marlow's avatar
Simon Marlow committed
663 664
    ACQUIRE_LOCK(&trace_utx);

665
    tracePreface();
666
    debugBelch("cap %d: ", cap->no);
667 668 669 670 671
    vdebugBelch(msg,ap);
    debugBelch("\n");

    RELEASE_LOCK(&trace_utx);
}
672 673 674 675 676 677 678 679

static void traceCap_stderr(Capability *cap, char *msg, ...)
{
  va_list ap;
  va_start(ap,msg);
  vtraceCap_stderr(cap, msg, ap);
  va_end(ap);
}
680 681
#endif

682
void traceCap_(Capability *cap, char *msg, ...)
683
{
684 685
    va_list ap;
    va_start(ap,msg);
686

Ben Gamari's avatar
Ben Gamari committed
687
#if defined(DEBUG)
688
    if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
689
        vtraceCap_stderr(cap, msg, ap);
690 691 692 693
    } else
#endif
    {
        postCapMsg(cap, msg, ap);
Simon Marlow's avatar
Simon Marlow committed
694
    }
695 696

    va_end(ap);
697 698
}

Ben Gamari's avatar
Ben Gamari committed
699
#if defined(DEBUG)
700
static void vtrace_stderr(char *msg, va_list ap)
701 702 703 704 705 706
{
    ACQUIRE_LOCK(&trace_utx);

    tracePreface();
    vdebugBelch(msg,ap);
    debugBelch("\n");
Simon Marlow's avatar
Simon Marlow committed
707 708

    RELEASE_LOCK(&trace_utx);
709 710
}
#endif
Simon Marlow's avatar
Simon Marlow committed
711

712
void trace_(char *msg, ...)
713
{
714 715 716
    va_list ap;
    va_start(ap,msg);

Ben Gamari's avatar
Ben Gamari committed
717
#if defined(DEBUG)
718
    if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
719
        vtrace_stderr(msg, ap);
720 721 722 723 724
    } else
#endif
    {
        postMsg(msg, ap);
    }
725 726

    va_end(ap);
Simon Marlow's avatar
Simon Marlow committed
727 728
}

729
void traceUserMsg(Capability *cap, char *msg)
730
{
731 732 733 734
    /* Note: normally we don't check the TRACE_* flags here as they're checked
       by the wrappers in Trace.h. But traceUserMsg is special since it has no
       wrapper (it's called from cmm code), so we check TRACE_user here
     */
Ben Gamari's avatar
Ben Gamari committed
735
#if defined(DEBUG)
736
    if (RtsFlags.TraceFlags.tracing == TRACE_STDERR && TRACE_user) {
737 738
        // Use "%s" as format string to ignore format specifiers in msg (#3874).
        traceCap_stderr(cap, "%s", msg);
739 740 741
    } else
#endif
    {
742
        if (eventlog_enabled && TRACE_user) {
743
            postUserEvent(cap, EVENT_USER_MSG, msg);
744 745
        }
    }
746
    dtraceUserMsg(cap->no, msg);
747 748
}

Mitsutoshi Aoe's avatar
Mitsutoshi Aoe committed
749 750 751 752 753 754 755 756 757 758 759
void traceUserBinaryMsg(Capability *cap, uint8_t *msg, size_t size)
{
    /* Note: normally we don't check the TRACE_* flags here as they're checked
       by the wrappers in Trace.h. But traceUserMsg is special since it has no
       wrapper (it's called from cmm code), so we check TRACE_user here
     */
    if (eventlog_enabled && TRACE_user) {
        postUserBinaryEvent(cap, EVENT_USER_BINARY_MSG, msg, size);
    }
}

760 761 762 763 764
void traceUserMarker(Capability *cap, char *markername)
{
    /* Note: traceUserMarker is special since it has no wrapper (it's called
       from cmm code), so we check eventlog_enabled and TRACE_user here.
     */
Ben Gamari's avatar
Ben Gamari committed
765
#if defined(DEBUG)
766
    if (RtsFlags.TraceFlags.tracing == TRACE_STDERR && TRACE_user) {
767
        traceCap_stderr(cap, "User marker: %s", markername);
768 769 770 771
    } else
#endif
    {
        if (eventlog_enabled && TRACE_user) {
772
            postUserEvent(cap, EVENT_USER_MARKER, markername);
773 774 775 776 777 778
        }
    }
    dtraceUserMarker(cap->no, markername);
}


779 780 781 782
void traceThreadLabel_(Capability *cap,
                       StgTSO     *tso,
                       char       *label)
{
Ben Gamari's avatar
Ben Gamari committed
783
#if defined(DEBUG)
784 785 786
    if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
        ACQUIRE_LOCK(&trace_utx);
        tracePreface();
Ian Lynagh's avatar
Ian Lynagh committed
787
        debugBelch("cap %d: thread %" FMT_Word " has label %s\n",
788
                   cap->no, (W_)tso->id, label);
789 790 791 792 793 794 795 796
        RELEASE_LOCK(&trace_utx);
    } else
#endif
    {
        postThreadLabel(cap, tso->id, label);
    }
}

797 798
void traceThreadStatus_ (StgTSO *tso USED_IF_DEBUG)
{
Ben Gamari's avatar
Ben Gamari committed
799
#if defined(DEBUG)
800
    if (RtsFlags.TraceFlags.tracing == TRACE_STDERR) {
801 802 803 804 805 806 807 808
        printThreadStatus(tso);
    } else
#endif
    {
        /* nothing - no event for this one yet */
    }
}

Ben Gamari's avatar
Ben Gamari committed
809
#if defined(DEBUG)
Simon Marlow's avatar
Simon Marlow committed
810 811 812 813 814 815 816 817 818
void traceBegin (const char *str, ...)
{
    va_list ap;
    va_start(ap,str);

    ACQUIRE_LOCK(&trace_utx);

    tracePreface();
    vdebugBelch(str,ap);
thomie's avatar
thomie committed
819
    va_end(ap);
Simon Marlow's avatar
Simon Marlow committed
820 821 822 823 824 825 826
}

void traceEnd (void)
{
    debugBelch("\n");
    RELEASE_LOCK(&trace_utx);
}
827
#endif /* DEBUG */
Simon Marlow's avatar
Simon Marlow committed
828

829
#endif /* TRACING */
830 831 832 833 834 835 836 837 838 839 840

// If DTRACE is enabled, but neither DEBUG nor TRACING, we need a C land
// wrapper for the user-msg probe (as we can't expand that in PrimOps.cmm)
//
#if !defined(DEBUG) && !defined(TRACING) && defined(DTRACE)

void dtraceUserMsgWrapper(Capability *cap, char *msg)
{
    dtraceUserMsg(cap->no, msg);
}

841 842 843 844 845
void dtraceUserMarkerWrapper(Capability *cap, char *msg)
{
    dtraceUserMarker(cap->no, msg);
}

846
#endif /* !defined(DEBUG) && !defined(TRACING) && defined(DTRACE) */