feat(scheduler-allocator-runner): plan generators initialise from the scheduling core (task 1.1)

xce_alloc_plan_iter_t.init takes xce_sched_core_t* instead of
xce_scheduler_t*; both built-in generators, both allocators' call sites
and the contract-test stub follow. The parjob purity test now shows an
identical plan sequence for a NULL and a poisoned core.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Rongsong Shen 2026-09-30 07:44:27 +00:00
parent e2266582b2
commit 86ee3491dd
Signed by untrusted user: rshen
GPG key ID: 80533536B0EB651C
6 changed files with 32 additions and 32 deletions

View file

@ -21,7 +21,7 @@
* is usable, not just that a struct literal type-checks.
*
* Both stub implementations ignore the real xce_primary_resreq_t/
* xce_scheduler_t/plan/workers arguments (ok, per the header's own
* xce_sched_core_t/plan/workers arguments (ok, per the header's own
* "each concrete plan-iterator implementation carries whatever it needs"
* note) and always yield exactly one candidate before signaling stable
* exhaustion.
@ -45,15 +45,15 @@ typedef struct {
static int stub_plan_iter_init(xce_alloc_plan_iter_t* iter,
xce_primary_resreq_t* resreq,
xce_scheduler_t* sched)
xce_sched_core_t* core)
{
stub_plan_priv_t* priv;
/* Stub: ignores the real resreq/sched state -- a real implementation
/* Stub: ignores the real resreq/core state -- a real implementation
* (parjob's combinatorial one, seqjob's trivial one) would derive its
* plan space from resreq->maxTasks here. */
(void)resreq;
(void)sched;
(void)core;
if (iter == NULL) {
return -EINVAL;

View file

@ -41,7 +41,7 @@
* - purity: plan shape/order is a pure function of maxTasks alone,
* never inspecting live worker/scheduler state (Req 4 AC 1's "never
* inspects live worker state" clause) -- proved by passing a NULL
* xce_scheduler_t* to init() and confirming plans still generate
* xce_sched_core_t* to init() and confirming plans still generate
* correctly
* - fini() releases the iterator's private state (Req 2 AC 5)
* - Req 2 AC 6: next() calls pthread_testcancel() (or an equivalent
@ -521,21 +521,21 @@ static void test_single_task_yields_single_plan(void)
/*
* Req 4 AC 1 ("never inspects live worker state" / "pure function of the
* task count alone"): the SAME maxTasks value must yield IDENTICAL plan
* sequences regardless of what (if anything) `sched` points to --
* including a NULL scheduler, and a garbage-but-non-NULL one whose
* fields are never touched. Since parjob_plan_iter_init()/_next() never
* dereference `sched` at all, a non-NULL "poisoned" scheduler pointer
* that would crash on any real field access is a stronger proof of
* purity than merely passing NULL.
* sequences regardless of what (if anything) `core` points to --
* including a NULL core, and a garbage-but-non-NULL one whose fields are
* never touched. Since parjob_plan_iter_init()/_next() never dereference
* `core` at all, a non-NULL "poisoned" core pointer that would crash on
* any real field access is a stronger proof of purity than merely
* passing NULL.
*/
static void test_plan_generation_ignores_scheduler_state(void)
static void test_plan_generation_ignores_core_state(void)
{
xce_primary_resreq_t resreq;
xce_alloc_plan_iter_t iter_a_storage;
xce_alloc_plan_iter_t* iter_a = &iter_a_storage;
xce_alloc_plan_iter_t iter_b_storage;
xce_alloc_plan_iter_t* iter_b = &iter_b_storage;
xce_scheduler_t* poisoned_sched = (xce_scheduler_t*)0x1;
xce_alloc_plan_iter_t* iter_b = &iter_b_storage;
xce_sched_core_t* poisoned_core = (xce_sched_core_t*)0x1;
int k;
memset(&resreq, 0, sizeof(resreq));
@ -549,7 +549,7 @@ static void test_plan_generation_ignores_scheduler_state(void)
/* A deliberately invalid, non-dereferenceable pointer -- init()/
* next() must never read through it, or this test would crash
* instead of merely failing an assertion. */
TEST_ASSERT_EQUAL_INT(0, iter_b->init(iter_b, &resreq, poisoned_sched));
TEST_ASSERT_EQUAL_INT(0, iter_b->init(iter_b, &resreq, poisoned_core));
for (k = 1; k <= 7; k++) {
xce_alloc_plan_t* plan_a = iter_a->next(iter_a);
@ -1229,7 +1229,7 @@ int main(void)
RUN_TEST(test_plans_ordered_ascending_host_count_with_balanced_partitions);
RUN_TEST(test_plans_for_evenly_divisible_task_count);
RUN_TEST(test_single_task_yields_single_plan);
RUN_TEST(test_plan_generation_ignores_scheduler_state);
RUN_TEST(test_plan_generation_ignores_core_state);
RUN_TEST(test_init_rejects_invalid_input);
RUN_TEST(test_next_has_a_real_cancellation_point);
RUN_TEST(test_multi_bucket_plan_succeeds_through_real_my_alloc);