feat(scheduler-sim-decision-trace): core trace gate and SCHED_TRACE hook macro

Task 1.8: the core gains trace_ctl/trace_rec (NULL unless the sim REPL
sets them) and SCHED_TRACE evaluates its call only while a record is
being built.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Rongsong Shen 2026-10-08 08:53:40 +00:00
parent 29b6734649
commit a801aff46f
Signed by untrusted user: rshen
GPG key ID: 80533536B0EB651C
6 changed files with 482 additions and 2 deletions

View file

@ -347,6 +347,30 @@ struct xce_sched_core_s {
* establishes for driver_ctx/on_decision.
*/
uint64_t prng_seed;
/*
* Decision trace gate (scheduler-sim-decision-trace spec, design.md
* "TraceModel"; Requirements 11.1-11.3). Two opaque pointers; the types
* are defined in sched/trace.h, which is not included here.
*
* trace_ctl: the session's trace settings. Only the simulator REPL
* writes it, from the driver thread inside the session window (set
* after the session begins, cleared after the drain loop); the
* allocator thread reads it once per picked job. The jbuf/wbuf
* cbuf handoffs order those accesses, so it is a plain pointer.
*
* trace_rec: the record being built for the job the allocator is
* working on. Only the allocator thread reads or writes it: set in the
* per-job prologue for a traced job, cleared when the record is handed
* away on a decision. SCHED_TRACE (sched/trace.h) runs its hook only
* while it is non-NULL.
*
* Both are NULL from xce_sched_core_init() (memset) and always NULL in
* the live scheduler and in a non-interactive simulation, which never
* publish settings. The core owns neither: xce_sched_core_fini() clears
* both without freeing them.
*/
struct xce_sched_trace_ctl_s* trace_ctl;
struct xce_sched_trace_rec_s* trace_rec;
};
/*

View file

@ -87,6 +87,21 @@ typedef struct xce_sched_trace_ctl_s {
typedef struct xce_sched_trace_rec_s xce_sched_trace_rec_t;
/*
* Hook gate (Requirement 11.2). `call` (a statement or expression, side
* effects and argument evaluation included) runs only while `core` (an
* xce_sched_core_t*) has a record under construction in trace_rec, so a
* hook costs one pointer test when nothing is traced, and nothing else.
* Only the allocator thread sets trace_rec, so hooks are placed only on
* that thread. One statement: safe in an unbraced if/else.
*/
#define SCHED_TRACE(core, call) \
do { \
if ((core)->trace_rec != NULL) { \
call; \
} \
} while (0)
#define XCE_TRACE_LINE_BOUND_DEFAULT 1000 /* Requirement 9.1 */
#define XCE_TRACE_LINE_BOUND_MIN 50
#define XCE_TRACE_LINE_BOUND_MAX 100000