feat(scheduler-sim-live-allocation): wire simulation mode onto shared picker/allocator (task 4.1)
Replaces sim_picker_thread_fn() (the always-PEND placeholder) with the real sched_job_picker()/sched_allocator() threads (task 3.1), spawned against &(sim->core) in sched_sim_driver_run(). Simulation mode now genuinely uses the jbuf capacity-1 rendezvous for the first time (confirmed still exactly one producer/one consumer). Adds sched_election.c to sched_sim_isolation_lib. Fixes bug-1829 (blocking, only reachable once sim_allocator() actually called sched_make_allocation() for the first time): core->seqjob_ allocator/parjob_allocator were never bootstrapped for simulation mode at all. Fixed via new sim_alloc.c (sim_bootstrap_seqjob_allocator()/ sim_bootstrap_parjob_allocator()), mirroring the sim_picker.c/ sim_limit.c precedent. That fix's own workaround -- a throwaway xce_scheduler_t wrapper satisfying seqjob/parjob's init_fn -- has a documented, narrow side effect: prepare_allocation_hook fan-out during a live seqjob/parjob dispatch attempt reaches the wrapper's own separate plugin registry, not sim->core.plugins, so a plugin registered only against the real sim core (the limit plugin) isn't reached for host-scoped matching during a live dispatch yet. Documented in design.md's new "Known Seam Gap" section; task 4.3 added to tasks.md to close it before task 5.2's acceptance test can pass for the host-scoped case. TDD: new end-to-end test drives a real .replay with an empty decisions array (ruling out reconciliation) through the real thread pair, proving a genuine DISPATCH from live resource availability. 25 pre-existing white-box sim/repl test files given link-satisfying stubs reproducing the OLD always-PEND contract unchanged -- their own assertions are untouched (task 5.3's job to reconcile deeper). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
This commit is contained in:
parent
4195331b47
commit
08df64930b
33 changed files with 3809 additions and 92 deletions
|
|
@ -273,6 +273,122 @@ int sched_resolve_job_picker(xce_sched_core_t* core, xce_sched_plugin_t** out)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* scheduler-sim-live-allocation spec, task 4.1: sim_loop.c's real
|
||||
* sched_sim_driver_run() (white-box #include'd into this TU above) now
|
||||
* spawns sched_job_picker()/sched_allocator() (sched_election.c) directly
|
||||
* instead of its own, now-removed sim_picker_thread_fn() -- an undefined
|
||||
* reference at link time in this white-box TU otherwise, since
|
||||
* sched_election.c's own sched_allocator() calls the REAL
|
||||
* sched_make_allocation()/sched_commit_decision() (scheduler.c), neither
|
||||
* part of this file's own hand-picked white-box #include set (this file's
|
||||
* own header comment lists that set). This file's own test(s) do not
|
||||
* exercise genuine resource-matching allocation, so this link-satisfying
|
||||
* pair faithfully reproduces the exact PEND-only contract the REMOVED
|
||||
* sim_picker_thread_fn() itself used to provide -- split across the SAME
|
||||
* two-thread jbuf hand-off the real production pair now uses (one
|
||||
* producer, one consumer, matching the project's jbuf capacity-1
|
||||
* rendezvous invariant) instead of the old single fused thread -- so this
|
||||
* file's own existing assertions are unaffected by this task's production
|
||||
* change. Genuine resource-based dispatch through the real, unmodified
|
||||
* sched_job_picker()/sched_allocator() pair is proved separately by
|
||||
* test_sim_live_allocation.c (task 4.1's own dedicated fixture, which
|
||||
* links the real scheduler_srcs instead of white-boxing individual files,
|
||||
* precisely so it can reach the real allocation chain this stub
|
||||
* deliberately does not). */
|
||||
void* sched_job_picker(void* arg)
|
||||
{
|
||||
xce_sched_core_t* core = (xce_sched_core_t*)arg;
|
||||
xce_sched_plugin_t* picker = NULL;
|
||||
|
||||
for (;;) {
|
||||
int go = 0;
|
||||
uint64_t jobid = 0;
|
||||
|
||||
cbuf_get(&(core->wbuf), &go);
|
||||
|
||||
if (sched_resolve_job_picker(core, &picker) < 0) {
|
||||
jobid = 0;
|
||||
cbuf_put(&(core->jbuf), &jobid);
|
||||
continue;
|
||||
}
|
||||
|
||||
picker->picker_iface->begin_session(picker);
|
||||
|
||||
for (;;) {
|
||||
xce_sched_job_t* job = picker->picker_iface->next_job(picker);
|
||||
|
||||
if (job == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
jobid = job->jobid;
|
||||
cbuf_put(&(core->jbuf), &jobid);
|
||||
}
|
||||
|
||||
jobid = 0;
|
||||
cbuf_put(&(core->jbuf), &jobid);
|
||||
|
||||
picker->picker_iface->end_session(picker);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* sched_allocator(void* arg)
|
||||
{
|
||||
xce_sched_core_t* core = (xce_sched_core_t*)arg;
|
||||
xce_sched_plugin_t* picker = NULL;
|
||||
|
||||
for (;;) {
|
||||
uint64_t jobid = 0;
|
||||
xce_decision_t* decision = NULL;
|
||||
xce_sched_job_t* job;
|
||||
|
||||
cbuf_get(&(core->jbuf), &jobid);
|
||||
if (jobid == 0) {
|
||||
decision = NULL;
|
||||
cbuf_put(&(core->decisions), &decision);
|
||||
continue;
|
||||
}
|
||||
|
||||
job = sched_get_job(core, jobid);
|
||||
if (job == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
(void)sched_resolve_job_picker(core, &picker);
|
||||
if (picker != NULL) {
|
||||
picker->picker_iface->on_pend(picker, job->jobid);
|
||||
}
|
||||
|
||||
decision = make_pend_decision(make_pendreason(job->jobid));
|
||||
cbuf_put(&(core->decisions), &decision);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* scheduler-sim-live-allocation spec, task 4.1 (bug-1829 fix): sim_loop.c's
|
||||
* real sched_sim_driver_run() (white-box #include'd into this TU above) now
|
||||
* also calls sim_bootstrap_seqjob_allocator()/sim_bootstrap_parjob_
|
||||
* allocator() (sim_alloc.c) -- undefined references at link time in this
|
||||
* white-box TU otherwise, since neither symbol is part of this file's own
|
||||
* hand-picked white-box #include set. This file's own test(s) exercise the
|
||||
* link-satisfying sched_job_picker()/sched_allocator() stub pair above
|
||||
* (which never reaches real primary allocation), so a true no-op is the
|
||||
* correct, behavior-preserving stand-in here -- the real bootstrap logic is
|
||||
* exercised separately by test_sim_live_allocation.c (task 4.1's own
|
||||
* dedicated fixture, which links the real scheduler_srcs). */
|
||||
void sim_bootstrap_seqjob_allocator(xce_sched_sim_driver_t* sim)
|
||||
{
|
||||
(void)sim;
|
||||
}
|
||||
|
||||
void sim_bootstrap_parjob_allocator(xce_sched_sim_driver_t* sim)
|
||||
{
|
||||
(void)sim;
|
||||
}
|
||||
|
||||
void setUp(void) { return; }
|
||||
void tearDown(void) { return; }
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue