feat(scheduler-core): extract xce_sched_core_t from monolithic scheduler struct (task 4.1)
Splits xce_scheduler_t along the controller-I/O seam: xce_sched_core_t
(new core.h/core.c) now holds all scheduling state (jobs/queues/workers/
users/projects/resource managers/plugins/three-thread-cbuf pipeline),
while xce_scheduler_t shrinks to {core; apictx; cluster_cfg}. Proven via
an nm-based link-time isolation test (zero netio/xcecli/idgen/delaymgr
symbols reachable from core.c) plus a reproducible wall-clock-call guard.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019dw5WnN3DXStaEaPYfACU1
This commit is contained in:
parent
604a564904
commit
7c229284e2
26 changed files with 1233 additions and 661 deletions
|
|
@ -12,12 +12,25 @@
|
|||
* This also brings in scheduler.h (with the real xce_scheduler_t) and all deps. */
|
||||
#include "../src/resource.c"
|
||||
|
||||
/* Stubs for symbols used by resource.c functions not under test */
|
||||
xce_sched_worker_t* sched_get_worker(xce_scheduler_t* s, char* n) { (void)s; (void)n; return NULL; }
|
||||
/* Stubs for symbols used by resource.c functions not under test.
|
||||
* sched_get_worker/sched_get_queue relocated to core.h (scheduler-core
|
||||
* spec, task 4.1) -- now operate on xce_sched_core_t*, not
|
||||
* xce_scheduler_t*. */
|
||||
xce_sched_worker_t* sched_get_worker(xce_sched_core_t* s, char* n)
|
||||
{
|
||||
(void)s;
|
||||
(void)n;
|
||||
return NULL;
|
||||
}
|
||||
int plugin_prepare_allocation(void* s, xce_sched_ctx_t* c) { (void)s; (void)c; return 0; }
|
||||
int sched_ctx_get_uncomit_host(xvec_t** v, xce_sched_ctx_t* c, int i) { (void)v; (void)c; (void)i; return 0; }
|
||||
int plugin_queue_update(void* s, xce_sched_queue_t* q) { (void)s; (void)q; return 0; }
|
||||
xce_sched_queue_t* sched_get_queue(xce_scheduler_t* s, char* n) { (void)s; (void)n; return NULL; }
|
||||
xce_sched_queue_t* sched_get_queue(xce_sched_core_t* s, char* n)
|
||||
{
|
||||
(void)s;
|
||||
(void)n;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Stub: sched_update_existing_queue returns -EINVAL when updated is NULL,
|
||||
* -ENOENT when queue not found (sched_get_queue stub returns NULL).
|
||||
|
|
@ -27,7 +40,7 @@ int sched_update_existing_queue(xce_scheduler_t* sched, xce_queue_t* updated)
|
|||
if (updated == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (sched_get_queue(sched, updated->queue) == NULL) {
|
||||
if (sched_get_queue(&(sched->core), updated->queue) == NULL) {
|
||||
return -ENOENT;
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -127,9 +140,9 @@ test_scheduler_t_has_atomic_gc_fields(void)
|
|||
xce_scheduler_t sched;
|
||||
memset(&sched, 0, sizeof(sched));
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(0, atomic_load(&sched.session_active));
|
||||
TEST_ASSERT_EQUAL_INT(0, atomic_load(&sched.eval_in_progress));
|
||||
TEST_ASSERT_EQUAL_INT(0, atomic_load(&sched.staging_merge_complete));
|
||||
TEST_ASSERT_EQUAL_INT(0, atomic_load(&sched.core.session_active));
|
||||
TEST_ASSERT_EQUAL_INT(0, atomic_load(&sched.core.eval_in_progress));
|
||||
TEST_ASSERT_EQUAL_INT(0, atomic_load(&sched.core.staging_merge_complete));
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -222,15 +235,15 @@ test_gc_predicates_idle_invariant(void)
|
|||
xce_scheduler_t sched;
|
||||
memset(&sched, 0, sizeof(sched));
|
||||
/* staging_merge_complete=1 means GC is safe to run */
|
||||
atomic_store(&sched.staging_merge_complete, 1);
|
||||
atomic_store(&sched.core.staging_merge_complete, 1);
|
||||
|
||||
sel_optimize_set(1);
|
||||
sel_node_table_init();
|
||||
|
||||
/* Verify the atomic fields are readable — testing the predicate contract */
|
||||
TEST_ASSERT_EQUAL_INT(0, atomic_load(&sched.session_active));
|
||||
TEST_ASSERT_EQUAL_INT(0, atomic_load(&sched.eval_in_progress));
|
||||
TEST_ASSERT_EQUAL_INT(1, atomic_load(&sched.staging_merge_complete));
|
||||
TEST_ASSERT_EQUAL_INT(0, atomic_load(&sched.core.session_active));
|
||||
TEST_ASSERT_EQUAL_INT(0, atomic_load(&sched.core.eval_in_progress));
|
||||
TEST_ASSERT_EQUAL_INT(1, atomic_load(&sched.core.staging_merge_complete));
|
||||
|
||||
/* GC operations on an empty node table must not crash */
|
||||
gc_clear_marks();
|
||||
|
|
@ -256,19 +269,20 @@ test_staging_merge_complete_gc_guard(void)
|
|||
memset(&sched, 0, sizeof(sched));
|
||||
|
||||
/* Simulate the post-begin_session state the fix produces */
|
||||
atomic_store(&sched.session_active, 0); /* session ended */
|
||||
atomic_store(&sched.eval_in_progress, 0);
|
||||
atomic_store(&sched.staging_merge_complete, 1); /* fix: begin_session sets this */
|
||||
atomic_store(&sched.core.session_active, 0); /* session ended */
|
||||
atomic_store(&sched.core.eval_in_progress, 0);
|
||||
atomic_store(&sched.core.staging_merge_complete,
|
||||
1); /* fix: begin_session sets this */
|
||||
|
||||
/* The GC guard in sched_end_session: must NOT fire */
|
||||
int guard_fires = atomic_load(&sched.eval_in_progress)
|
||||
|| !atomic_load(&sched.staging_merge_complete);
|
||||
int guard_fires = atomic_load(&sched.core.eval_in_progress)
|
||||
|| !atomic_load(&sched.core.staging_merge_complete);
|
||||
TEST_ASSERT_EQUAL_INT(0, guard_fires);
|
||||
|
||||
/* Confirm the unfixed state (staging=0) would block GC */
|
||||
atomic_store(&sched.staging_merge_complete, 0);
|
||||
int guard_fires_unfixed = atomic_load(&sched.eval_in_progress)
|
||||
|| !atomic_load(&sched.staging_merge_complete);
|
||||
atomic_store(&sched.core.staging_merge_complete, 0);
|
||||
int guard_fires_unfixed = atomic_load(&sched.core.eval_in_progress)
|
||||
|| !atomic_load(&sched.core.staging_merge_complete);
|
||||
TEST_ASSERT_EQUAL_INT(1, guard_fires_unfixed);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue