1/* @title: Per-thread diagnostics */
2#pragma once
3#include <atomic.h>
4#include <stddef.h>
5#include <stdint.h>
6#include <thread/thread_types.h>
7#include <time/time.h>
8
9struct thread;
10
11#define THREAD_WAIT_TRACE_DEPTH UINT64_C(16)
12
13struct thread_wait_arm {
14 const char *site; /* which arming path */
15 void *ra; /* caller of arm */
16 void *object; /* first registered object (NULL for park) */
17 uint64_t first_epoch; /* wait epoch when this descriptor was installed */
18 uint64_t last_epoch; /* wait epoch of the most recent identical arm */
19 uint64_t repeats; /* consecutive arms carrying this descriptor */
20 time_ms_t last_ms;
21 uint8_t state; /* enum thread_state armed into */
22 uint8_t wait_type; /* enum thread_wait_type armed with */
23 thread_act_reason_t reason; /* block/sleep reason byte */
24 uint16_t block_count;
25};
26
27struct thread_diag {
28 struct thread_wait_arm wait_trace[THREAD_WAIT_TRACE_DEPTH];
29 uint64_t wait_arm_count;
30 uint64_t wait_arm_total;
31
32 uint64_t apc_deliver_entries; /* calls to deliver_apc_type() */
33 uint64_t apc_deliver_max; /* most APCs drained by a single call */
34 void *apc_last_deliver_ra; /* who called apc_check_and_deliver() */
35};
36
37bool thread_diag_attach(struct thread *t, struct thread_diag *d);
38
39void thread_diag_detach(struct thread *t);
40
41struct thread_diag *thread_diag(struct thread *t);
42
43void thread_diag_record_arm(struct thread *t, const char *site, void *ra,
44 void *object, enum thread_state state,
45 enum thread_wait_type type, uint8_t reason);
46
47void thread_diag_apc_deliver_enter(struct thread *t, void *ra);
48void thread_diag_apc_deliver_batch(struct thread *t, uint64_t drained);
49
50void thread_dump_wait_trace(struct thread *t, const char *role, size_t idx,
51 uint64_t max_arms);
52