| 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 | |
| 9 | struct thread; |
| 10 | |
| 11 | #define THREAD_WAIT_TRACE_DEPTH UINT64_C(16) |
| 12 | |
| 13 | struct 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 | |
| 27 | struct 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 | |
| 37 | bool thread_diag_attach(struct thread *t, struct thread_diag *d); |
| 38 | |
| 39 | void thread_diag_detach(struct thread *t); |
| 40 | |
| 41 | struct thread_diag *thread_diag(struct thread *t); |
| 42 | |
| 43 | void 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 | |
| 47 | void thread_diag_apc_deliver_enter(struct thread *t, void *ra); |
| 48 | void thread_diag_apc_deliver_batch(struct thread *t, uint64_t drained); |
| 49 | |
| 50 | void thread_dump_wait_trace(struct thread *t, const char *role, size_t idx, |
| 51 | uint64_t max_arms); |
| 52 | |