feat(scheduler-sim-live-allocation): make capacity checks core-safe (task 1.3)
Re-types sched_meet_host_selection(), sched_check_shared_satisfy() (+its _ helper), sched_check_host_satisfy() (+its _ helper), and the private unsatisfy_() helper they share, from xce_scheduler_t* to xce_sched_core_t*, in resource.c. Fixes every call site this forces (a C signature migration cannot keep the build green otherwise): sched_try_alloc_on_host_() (2 sites, already partially touched by task 1.2), host_iter.c's sched_host_iter_next() (2 sites), and parjob_allocator.c/ seqjob_allocator.c's my_alloc() (1 site each) -- each fix is a minimal &(sched->core) argument wrap, no algorithm change, preserving host_iter/parjob/seqjob's own allocation algorithm exactly as-is. Adds test_core_safe_allocation_chain_driver_parity, proving all three functions produce identical grant/deny results whether given normal-mode-shaped or simulation-mode-shaped core state. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
This commit is contained in:
parent
e8866641a6
commit
55173fca27
13 changed files with 345 additions and 53 deletions
|
|
@ -17,7 +17,7 @@
|
|||
- _Requirements: 1.1, 2.1, 2.2, 5.1_
|
||||
- _Boundary: Plugin Hook Dispatchers_
|
||||
|
||||
- [ ] 1.3 (P) Make the per-host and shared capacity checks driver-agnostic
|
||||
- [x] 1.3 (P) Make the per-host and shared capacity checks driver-agnostic
|
||||
- Re-type the host-selection match, shared-capacity check, and per-host capacity check functions to operate on shared core state directly instead of a normal-mode-only driver struct
|
||||
- TDD: re-run their existing unit tests unchanged (pure signature migration) plus a new test calling each function with core state drawn from a simulation-mode-shaped container, confirming identical results to the normal-mode-shaped case
|
||||
- Observable: these three functions compile and pass identically regardless of which driver's core state they're given
|
||||
|
|
@ -114,4 +114,5 @@
|
|||
## Implementation Notes
|
||||
|
||||
- **Task 1.1**: initial submission implemented before tests were written (TDD-mandate violation, caught in review round 1) — the real RED phase must be captured by reverting production files to HEAD via a saved patch + `git checkout --`, rebuilding to see the genuine failure, then reapplying. Retroactively-written tests plus a passing GREEN build alone do not satisfy this project's TDD discipline; the reviewer independently re-derives RED by reverting your changes, so skipping this is always caught.
|
||||
- **Task 1.3**: grep for ALL call sites of a function before migrating it, not just the ones named in the task brief — `host_iter.c`'s `sched_host_iter_next()` and `parjob_allocator.c`/`seqjob_allocator.c`'s `my_alloc()` all call the capacity-check functions directly, not only via `sched_try_alloc_on_host_()`. A private `static` helper with no other callers besides the functions being migrated should be migrated alongside them (leaving it stale forces an ugly cast, which this codebase's own design explicitly forbids in shared code).
|
||||
- **Task 1.2**: retyping a widely-called function's signature (e.g. `plugin_job_election`, `plugin_prepare_allocation`, `plugin_commit_decision`) breaks ALL of its call sites as hard compile errors in one step (this toolchain treats `-Wincompatible-pointer-types` as an error, not a warning) — there is no way to migrate a signature and keep the build green without touching every call site in the same commit, even when those call sites live in files nominally owned by a later task. The correct scope is the *minimal* fix (wrap the existing argument, e.g. `sched` → `&(sched->core)`; touch nothing else in that function), not a rewrite of the caller. Also: design.md's Implementation Notes said `plugin_prepare_allocation()` has "one normal-mode call site" — it actually has two (`resource.c`'s `sched_try_alloc_on_host_()` and `schedobj.c`'s `sched_ctx_set_primary()`). Grep for ALL call sites before assuming a design doc's count is exhaustive.
|
||||
|
|
|
|||
|
|
@ -336,11 +336,17 @@ extern int sched_publish_dispatch(xce_scheduler_t*, xce_job_dispatch_t*);
|
|||
* function for the chicken-and-egg deadlock this closes. */
|
||||
extern void sched_check_pending_rejoin(xce_scheduler_t*);
|
||||
extern void sched_worker_release_host_ctx(xce_sched_worker_t*);
|
||||
extern int sched_meet_host_selection(xce_scheduler_t*, xce_sched_worker_t*,
|
||||
/* scheduler-sim-live-allocation spec, task 1.3: retyped from
|
||||
* xce_scheduler_t* to xce_sched_core_t* -- these three now operate on
|
||||
* shared core state directly, callable identically from either driver
|
||||
* (both xce_scheduler_t and xce_sched_sim_driver_t embed xce_sched_core_t
|
||||
* core as their first member). Body unchanged besides sched->core.X ->
|
||||
* core->X field-access updates. */
|
||||
extern int sched_meet_host_selection(xce_sched_core_t*, xce_sched_worker_t*,
|
||||
xce_select_t*);
|
||||
extern int sched_check_shared_satisfy(xce_scheduler_t*, xvec_t*, xvec_idval_t*,
|
||||
extern int sched_check_shared_satisfy(xce_sched_core_t*, xvec_t*, xvec_idval_t*,
|
||||
xvec_idval_t*);
|
||||
extern int sched_check_host_satisfy(xce_scheduler_t*, xce_sched_worker_t*,
|
||||
extern int sched_check_host_satisfy(xce_sched_core_t*, xce_sched_worker_t*,
|
||||
xvec_t*, xvec_idval_t*, xvec_idval_t*);
|
||||
extern int sched_collect_workers(xce_scheduler_t*, xlist_t*,
|
||||
zarray_iter_skip_fn_t,
|
||||
|
|
|
|||
|
|
@ -129,9 +129,14 @@ xce_sched_worker_t* sched_host_iter_next(xce_host_iter_t* iter)
|
|||
continue;
|
||||
}
|
||||
|
||||
/* 1. Select-expression filter -- existing evaluator, unchanged. */
|
||||
/* 1. Select-expression filter -- existing evaluator, unchanged.
|
||||
* scheduler-sim-live-allocation task 1.3: sched_meet_host_
|
||||
* selection() is now core-typed -- minimal &(sched->core) wrap;
|
||||
* `sched` itself (derived from ctx->sched) keeps its existing
|
||||
* xce_scheduler_t* type here, since that field's own migration to
|
||||
* shared core state is task 2.1's job. */
|
||||
if (!sched_meet_host_selection(
|
||||
sched, w,
|
||||
&(sched->core), w,
|
||||
(ctx->primary != NULL) ? ctx->primary->select : NULL)) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -152,7 +157,9 @@ xce_sched_worker_t* sched_host_iter_next(xce_host_iter_t* iter)
|
|||
continue;
|
||||
}
|
||||
|
||||
rc = sched_check_host_satisfy(sched, w, uncomit,
|
||||
/* task 1.3: sched_check_host_satisfy() is now core-typed too --
|
||||
* same minimal &(sched->core) wrap as above. */
|
||||
rc = sched_check_host_satisfy(&(sched->core), w, uncomit,
|
||||
&(ctx->alloc_req.host),
|
||||
&(ctx->unmeet));
|
||||
if (rc <= 0) {
|
||||
|
|
|
|||
|
|
@ -587,8 +587,12 @@ static int my_alloc(xce_sched_plugin_t* plugin, xce_sched_ctx_t* ctx)
|
|||
return rc;
|
||||
}
|
||||
|
||||
rc = sched_check_shared_satisfy(sched, uncomit, &(ctx->alloc_req.shared),
|
||||
&(ctx->unmeet));
|
||||
/* scheduler-sim-live-allocation task 1.3: sched_check_shared_satisfy()
|
||||
* is now core-typed -- minimal &(sched->core) wrap; `sched` itself
|
||||
* keeps its existing xce_scheduler_t* type here (derived from
|
||||
* plugin->sched), unchanged by this task. */
|
||||
rc = sched_check_shared_satisfy(&(sched->core), uncomit,
|
||||
&(ctx->alloc_req.shared), &(ctx->unmeet));
|
||||
if (rc < 0) {
|
||||
return rc;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -225,8 +225,12 @@ static int my_alloc(xce_sched_plugin_t* plugin, xce_sched_ctx_t* ctx)
|
|||
return rc;
|
||||
}
|
||||
|
||||
rc = sched_check_shared_satisfy(sched, uncomit, &(ctx->alloc_req.shared),
|
||||
&(ctx->unmeet));
|
||||
/* scheduler-sim-live-allocation task 1.3: sched_check_shared_satisfy()
|
||||
* is now core-typed -- minimal &(sched->core) wrap; `sched` itself
|
||||
* keeps its existing xce_scheduler_t* type here (derived from
|
||||
* plugin->sched), unchanged by this task. */
|
||||
rc = sched_check_shared_satisfy(&(sched->core), uncomit,
|
||||
&(ctx->alloc_req.shared), &(ctx->unmeet));
|
||||
if (rc < 0) {
|
||||
return rc;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ int put_resvals(zarray_t* array, int nres, int* idxs, float* vals)
|
|||
return nres;
|
||||
}
|
||||
|
||||
static int unsatisfy_(xce_scheduler_t* sched, int nres, int* idxs, float* total,
|
||||
static int unsatisfy_(xce_sched_core_t* core, int nres, int* idxs, float* total,
|
||||
float* inuse, float* uncomitted, float* wanted,
|
||||
int* unmeet_idxs, float* unmeet_vals)
|
||||
{
|
||||
|
|
@ -142,7 +142,7 @@ static int unsatisfy_(xce_scheduler_t* sched, int nres, int* idxs, float* total,
|
|||
xce_resource_t* r = NULL;
|
||||
float need = inuse[i] + uncomitted[i] + wanted[i] - total[i];
|
||||
|
||||
vget(sched->core.resmgr, idxs[i], (void**)&r);
|
||||
vget(core->resmgr, idxs[i], (void**)&r);
|
||||
TRACE("%s unmet resource %d (%s) shortfall %f", __func__, idxs[i],
|
||||
r ? r->name : "?", need);
|
||||
|
||||
|
|
@ -218,7 +218,7 @@ void sched_worker_release_host_ctx(xce_sched_worker_t* w)
|
|||
w->host_eval_ctx = NULL;
|
||||
}
|
||||
|
||||
int sched_meet_host_selection(xce_scheduler_t* sched, xce_sched_worker_t* w,
|
||||
int sched_meet_host_selection(xce_sched_core_t* core, xce_sched_worker_t* w,
|
||||
xce_select_t* s)
|
||||
{
|
||||
if (s == NULL || s->root == NULL)
|
||||
|
|
@ -235,12 +235,12 @@ int sched_meet_host_selection(xce_scheduler_t* sched, xce_sched_worker_t* w,
|
|||
}
|
||||
|
||||
/* Fast path: use session-level memoisation context when available. */
|
||||
if (sched->core.sel_eval_ctx != NULL) {
|
||||
if (core->sel_eval_ctx != NULL) {
|
||||
/* Reset memoisation bitmap only when moving to a different host. */
|
||||
if (sched->core.sel_eval_ctx->host != w->host_eval_ctx)
|
||||
select_eval_ctx_reset(sched->core.sel_eval_ctx, w->host_eval_ctx);
|
||||
if (core->sel_eval_ctx->host != w->host_eval_ctx)
|
||||
select_eval_ctx_reset(core->sel_eval_ctx, w->host_eval_ctx);
|
||||
|
||||
int rc = eval_select(s->root, sched->core.sel_eval_ctx);
|
||||
int rc = eval_select(s->root, core->sel_eval_ctx);
|
||||
return (rc > 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
|
@ -250,7 +250,7 @@ int sched_meet_host_selection(xce_scheduler_t* sched, xce_sched_worker_t* w,
|
|||
return (rc > 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int sched_check_shared_satisfy_(xce_scheduler_t* sched, xvec_t* total,
|
||||
static int sched_check_shared_satisfy_(xce_sched_core_t* core, xvec_t* total,
|
||||
xvec_t* inuse, xvec_t* uncomitted,
|
||||
xvec_idval_t* wanted,
|
||||
xvec_idval_t* unmeet)
|
||||
|
|
@ -273,19 +273,19 @@ static int sched_check_shared_satisfy_(xce_scheduler_t* sched, xvec_t* total,
|
|||
return rc;
|
||||
}
|
||||
|
||||
rc = get_resvals(&(sched->core.sharedInst), nres, (int*)wanted->idxs.data,
|
||||
rc = get_resvals(&(core->sharedInst), nres, (int*)wanted->idxs.data,
|
||||
(float*)total->data);
|
||||
if (rc < 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = get_resvals(&(sched->core.sharedInUse), nres, (int*)wanted->idxs.data,
|
||||
rc = get_resvals(&(core->sharedInUse), nres, (int*)wanted->idxs.data,
|
||||
(float*)inuse->data);
|
||||
if (rc < 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = unsatisfy_(sched, nres, (int*)wanted->idxs.data, (float*)total->data,
|
||||
rc = unsatisfy_(core, nres, (int*)wanted->idxs.data, (float*)total->data,
|
||||
(float*)inuse->data, (float*)uncomitted->data,
|
||||
(float*)wanted->vals.data, (int*)unmeet->idxs.data,
|
||||
(float*)unmeet->vals.data);
|
||||
|
|
@ -302,7 +302,7 @@ static int sched_check_shared_satisfy_(xce_scheduler_t* sched, xvec_t* total,
|
|||
return 1;
|
||||
}
|
||||
|
||||
int sched_check_shared_satisfy(xce_scheduler_t* sched, xvec_t* uncomitted,
|
||||
int sched_check_shared_satisfy(xce_sched_core_t* core, xvec_t* uncomitted,
|
||||
xvec_idval_t* wanted, xvec_idval_t* unmeet)
|
||||
{
|
||||
xvec_t total;
|
||||
|
|
@ -313,7 +313,7 @@ int sched_check_shared_satisfy(xce_scheduler_t* sched, xvec_t* uncomitted,
|
|||
return 1;
|
||||
}
|
||||
|
||||
rc = sched_check_shared_satisfy_(sched, &total, &inuse, uncomitted, wanted,
|
||||
rc = sched_check_shared_satisfy_(core, &total, &inuse, uncomitted, wanted,
|
||||
unmeet);
|
||||
if (rc < 0) {
|
||||
xvec_idval_fini(unmeet);
|
||||
|
|
@ -325,7 +325,7 @@ int sched_check_shared_satisfy(xce_scheduler_t* sched, xvec_t* uncomitted,
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int sched_check_host_satisfy_(xce_scheduler_t* sched,
|
||||
static int sched_check_host_satisfy_(xce_sched_core_t* core,
|
||||
xce_sched_worker_t* w, xvec_t* total,
|
||||
xvec_t* inuse, xvec_t* uncomitted,
|
||||
xvec_idval_t* wanted, xvec_idval_t* unmeet)
|
||||
|
|
@ -360,7 +360,7 @@ static int sched_check_host_satisfy_(xce_scheduler_t* sched,
|
|||
return rc;
|
||||
}
|
||||
|
||||
rc = unsatisfy_(sched, nres, (int*)wanted->idxs.data, (float*)total->data,
|
||||
rc = unsatisfy_(core, nres, (int*)wanted->idxs.data, (float*)total->data,
|
||||
(float*)inuse->data, (float*)uncomitted->data,
|
||||
(float*)wanted->vals.data, (int*)unmeet->idxs.data,
|
||||
(float*)unmeet->vals.data);
|
||||
|
|
@ -375,7 +375,7 @@ static int sched_check_host_satisfy_(xce_scheduler_t* sched,
|
|||
|
||||
return 1;
|
||||
}
|
||||
int sched_check_host_satisfy(xce_scheduler_t* sched, xce_sched_worker_t* w,
|
||||
int sched_check_host_satisfy(xce_sched_core_t* core, xce_sched_worker_t* w,
|
||||
xvec_t* uncomitted, xvec_idval_t* wanted,
|
||||
xvec_idval_t* unmeet)
|
||||
{
|
||||
|
|
@ -387,7 +387,7 @@ int sched_check_host_satisfy(xce_scheduler_t* sched, xce_sched_worker_t* w,
|
|||
return 1;
|
||||
}
|
||||
|
||||
rc = sched_check_host_satisfy_(sched, w, &total, &inuse, uncomitted, wanted,
|
||||
rc = sched_check_host_satisfy_(core, w, &total, &inuse, uncomitted, wanted,
|
||||
unmeet);
|
||||
if (rc < 0) {
|
||||
xvec_idval_fini(unmeet);
|
||||
|
|
@ -502,7 +502,13 @@ int sched_try_alloc_on_host_(xce_sched_worker_t* w, xce_scheduler_t* sched,
|
|||
int rc;
|
||||
xvec_t* uncomit = NULL;
|
||||
|
||||
rc = sched_meet_host_selection(sched, w, primary->select);
|
||||
/* scheduler-sim-live-allocation spec, task 1.3: sched_meet_host_
|
||||
* selection() is now core-typed -- pass &(sched->core), the same
|
||||
* minimal call-site update task 1.2 made for plugin_prepare_
|
||||
* allocation() just below. sched_try_alloc_on_host_() itself keeps its
|
||||
* existing xce_scheduler_t* sched parameter unchanged (that retyping
|
||||
* is task 2.1's job, "Core-Safe Allocation Chain"). */
|
||||
rc = sched_meet_host_selection(&(sched->core), w, primary->select);
|
||||
if (rc == 0) {
|
||||
if (ctx->reason == NULL) {
|
||||
ctx->reason = make_pendreason(0);
|
||||
|
|
@ -539,8 +545,10 @@ int sched_try_alloc_on_host_(xce_sched_worker_t* w, xce_scheduler_t* sched,
|
|||
return rc;
|
||||
}
|
||||
|
||||
rc = sched_check_host_satisfy(sched, w, uncomit, &(ctx->alloc_req.host),
|
||||
&(ctx->unmeet));
|
||||
/* task 1.3: sched_check_host_satisfy() is now core-typed too -- same
|
||||
* minimal &(sched->core) wrap as sched_meet_host_selection() above. */
|
||||
rc = sched_check_host_satisfy(&(sched->core), w, uncomit,
|
||||
&(ctx->alloc_req.host), &(ctx->unmeet));
|
||||
if (rc < 0) {
|
||||
/* FIXME: */
|
||||
return rc;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,12 @@
|
|||
* This also brings in scheduler.h (with the real xce_scheduler_t) and all deps. */
|
||||
#include "../src/resource.c"
|
||||
|
||||
/* scheduler-sim-live-allocation spec, task 1.3: sim.h only depends on
|
||||
* core.h (+ stdbool/stdint/stdio, per its own header comment), so it is
|
||||
* safe to pull in here just for xce_sched_sim_driver_t -- needed to build
|
||||
* a simulation-mode-shaped container for the driver-parity test below. */
|
||||
#include "sim.h"
|
||||
|
||||
/* 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
|
||||
|
|
@ -167,7 +173,7 @@ test_meet_host_selection_null_select_passes(void)
|
|||
memset(&w, 0, sizeof(w));
|
||||
zarray_init(&w.resvals, 4, NULL);
|
||||
|
||||
int rc = sched_meet_host_selection(&sched, &w, NULL);
|
||||
int rc = sched_meet_host_selection(&(sched.core), &w, NULL);
|
||||
TEST_ASSERT_EQUAL_INT(1, rc);
|
||||
|
||||
zarray_fini(&w.resvals);
|
||||
|
|
@ -190,7 +196,7 @@ test_meet_host_selection_always_true_passes(void)
|
|||
TEST_ASSERT_NOT_NULL(root);
|
||||
|
||||
xce_select_t sel = { .root = root };
|
||||
int rc = sched_meet_host_selection(&sched, &w, &sel);
|
||||
int rc = sched_meet_host_selection(&(sched.core), &w, &sel);
|
||||
TEST_ASSERT_EQUAL_INT(1, rc);
|
||||
|
||||
sched_worker_release_host_ctx(&w);
|
||||
|
|
@ -218,7 +224,7 @@ test_meet_host_selection_always_false_fails(void)
|
|||
TEST_ASSERT_NOT_NULL(root);
|
||||
|
||||
xce_select_t sel = { .root = root };
|
||||
int rc = sched_meet_host_selection(&sched, &w, &sel);
|
||||
int rc = sched_meet_host_selection(&(sched.core), &w, &sel);
|
||||
TEST_ASSERT_EQUAL_INT(0, rc);
|
||||
|
||||
sched_worker_release_host_ctx(&w);
|
||||
|
|
@ -323,7 +329,7 @@ test_meet_host_selection_numeric_match(void)
|
|||
v8.u.fvalue = 8.0f;
|
||||
zarray_put(&w8.resvals, 0, &v8);
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(1, sched_meet_host_selection(&sched, &w8, &sel));
|
||||
TEST_ASSERT_EQUAL_INT(1, sched_meet_host_selection(&(sched.core), &w8, &sel));
|
||||
|
||||
/* Worker with 2.0 at res_idx=0 — must fail */
|
||||
xce_sched_worker_t w2;
|
||||
|
|
@ -336,7 +342,7 @@ test_meet_host_selection_numeric_match(void)
|
|||
v2.u.fvalue = 2.0f;
|
||||
zarray_put(&w2.resvals, 0, &v2);
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(0, sched_meet_host_selection(&sched, &w2, &sel));
|
||||
TEST_ASSERT_EQUAL_INT(0, sched_meet_host_selection(&(sched.core), &w2, &sel));
|
||||
|
||||
sched_worker_release_host_ctx(&w8);
|
||||
sched_worker_release_host_ctx(&w2);
|
||||
|
|
@ -382,7 +388,7 @@ test_meet_host_selection_string_match(void)
|
|||
vgpu.u.svalue = "gpu";
|
||||
zarray_put(&wgpu.resvals, 1, &vgpu);
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(1, sched_meet_host_selection(&sched, &wgpu, &sel));
|
||||
TEST_ASSERT_EQUAL_INT(1, sched_meet_host_selection(&(sched.core), &wgpu, &sel));
|
||||
|
||||
/* Worker with "cpu" at res_idx=1 — must fail */
|
||||
xce_sched_worker_t wcpu;
|
||||
|
|
@ -395,7 +401,7 @@ test_meet_host_selection_string_match(void)
|
|||
vcpu.u.svalue = "cpu";
|
||||
zarray_put(&wcpu.resvals, 1, &vcpu);
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(0, sched_meet_host_selection(&sched, &wcpu, &sel));
|
||||
TEST_ASSERT_EQUAL_INT(0, sched_meet_host_selection(&(sched.core), &wcpu, &sel));
|
||||
|
||||
sched_worker_release_host_ctx(&wgpu);
|
||||
sched_worker_release_host_ctx(&wcpu);
|
||||
|
|
@ -477,6 +483,248 @@ test_dead_pushmsg_symbols_absent(void)
|
|||
TEST_PASS();
|
||||
}
|
||||
|
||||
/* ── scheduler-sim-live-allocation task 1.3: Core-Safe Allocation Chain ── */
|
||||
|
||||
/*
|
||||
* sched_meet_host_selection()/sched_check_shared_satisfy()/
|
||||
* sched_check_host_satisfy() are re-typed to take xce_sched_core_t* core
|
||||
* directly instead of a normal-mode-only xce_scheduler_t* sched, so they
|
||||
* must be callable identically from either driver's core state --
|
||||
* xce_scheduler_t (this file's own `sched` variables above) and
|
||||
* xce_sched_sim_driver_t (sim.h) both embed xce_sched_core_t core as their
|
||||
* first member (scheduler.h / sim.h). This test drives IDENTICAL inputs
|
||||
* through all three functions against &(normal.core) and &(sim.core) and
|
||||
* asserts identical results -- proving driver-agnosticism, not merely a
|
||||
* retyped signature.
|
||||
*
|
||||
* RED (before this task): fails to compile -- the three functions take
|
||||
* xce_scheduler_t*, so passing xce_sched_core_t* directly is an
|
||||
* incompatible-pointer-type error (this toolchain treats
|
||||
* -Wincompatible-pointer-types as fatal, not a warning).
|
||||
*
|
||||
* No sched_sim_driver_run() call here -- this fixture never spawns a
|
||||
* thread against xce_sched_sim_driver_t, only reads/writes its embedded
|
||||
* `core` synchronously within this function's own lifetime, so bug-1598's
|
||||
* stack-use-after-return hazard (a stack-local sim driver outliving a
|
||||
* never-joined thread) does not apply.
|
||||
*/
|
||||
static void init_test_resmgr(xce_sched_core_t* core)
|
||||
{
|
||||
kvmgr_params_t resmgr_params = { .key_type = KVMGR_KEY_STRING,
|
||||
.nslots = 8,
|
||||
.delta = 4,
|
||||
.datakiller = NULL };
|
||||
|
||||
core->resmgr = makeInstance(&xkvmgr_type, &resmgr_params);
|
||||
TEST_ASSERT_NOT_NULL(core->resmgr);
|
||||
}
|
||||
|
||||
static void
|
||||
test_core_safe_allocation_chain_driver_parity(void)
|
||||
{
|
||||
xce_scheduler_t sched_normal;
|
||||
xce_sched_sim_driver_t sim_shape;
|
||||
xce_sched_core_t* core_normal = &(sched_normal.core);
|
||||
xce_sched_core_t* core_sim = &(sim_shape.core);
|
||||
|
||||
memset(&sched_normal, 0, sizeof(sched_normal));
|
||||
memset(&sim_shape, 0, sizeof(sim_shape));
|
||||
init_test_resmgr(core_normal);
|
||||
init_test_resmgr(core_sim);
|
||||
|
||||
/* --- sched_meet_host_selection(): NULL select always passes -------- */
|
||||
{
|
||||
xce_sched_worker_t w;
|
||||
int rc_normal, rc_sim;
|
||||
|
||||
memset(&w, 0, sizeof(w));
|
||||
zarray_init(&w.resvals, 4, NULL);
|
||||
|
||||
rc_normal = sched_meet_host_selection(core_normal, &w, NULL);
|
||||
rc_sim = sched_meet_host_selection(core_sim, &w, NULL);
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(1, rc_normal);
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(
|
||||
rc_normal, rc_sim,
|
||||
"sched_meet_host_selection() must return identically for a "
|
||||
"normal-mode-shaped and a simulation-mode-shaped core");
|
||||
|
||||
zarray_fini(&w.resvals);
|
||||
}
|
||||
|
||||
/* --- sched_check_shared_satisfy(): identical grant/deny ------------- */
|
||||
{
|
||||
xvec_t uncomitted_n, uncomitted_s;
|
||||
xvec_idval_t wanted_n, wanted_s, unmeet_n, unmeet_s;
|
||||
xce_val_t total, inuse;
|
||||
int rc_normal, rc_sim;
|
||||
|
||||
zarray_init(&core_normal->sharedInst, 4, NULL);
|
||||
zarray_init(&core_normal->sharedInUse, 4, NULL);
|
||||
zarray_init(&core_sim->sharedInst, 4, NULL);
|
||||
zarray_init(&core_sim->sharedInUse, 4, NULL);
|
||||
|
||||
memset(&total, 0, sizeof(total));
|
||||
total.which = Value_u_fvalue;
|
||||
total.u.fvalue = 10.0f;
|
||||
memset(&inuse, 0, sizeof(inuse));
|
||||
inuse.which = Value_u_fvalue;
|
||||
inuse.u.fvalue = 3.0f;
|
||||
|
||||
zarray_put(&core_normal->sharedInst, 0, &total);
|
||||
zarray_put(&core_normal->sharedInUse, 0, &inuse);
|
||||
zarray_put(&core_sim->sharedInst, 0, &total);
|
||||
zarray_put(&core_sim->sharedInUse, 0, &inuse);
|
||||
|
||||
/* Grant: wants 5.0, only 3.0 in use out of 10.0 total. */
|
||||
xvec_init(&uncomitted_n, 1, sizeof(float));
|
||||
xvec_idval_init(&wanted_n, 1);
|
||||
xvec_idval_store(&wanted_n, 0, 5.0f);
|
||||
xvec_init(&uncomitted_s, 1, sizeof(float));
|
||||
xvec_idval_init(&wanted_s, 1);
|
||||
xvec_idval_store(&wanted_s, 0, 5.0f);
|
||||
|
||||
rc_normal = sched_check_shared_satisfy(core_normal, &uncomitted_n,
|
||||
&wanted_n, &unmeet_n);
|
||||
rc_sim = sched_check_shared_satisfy(core_sim, &uncomitted_s,
|
||||
&wanted_s, &unmeet_s);
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(1, rc_normal);
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(
|
||||
rc_normal, rc_sim,
|
||||
"sched_check_shared_satisfy() must grant identically for a "
|
||||
"normal-mode-shaped and a simulation-mode-shaped core");
|
||||
|
||||
xvec_fini(&uncomitted_n);
|
||||
xvec_idval_fini(&wanted_n);
|
||||
xvec_idval_fini(&unmeet_n);
|
||||
xvec_fini(&uncomitted_s);
|
||||
xvec_idval_fini(&wanted_s);
|
||||
xvec_idval_fini(&unmeet_s);
|
||||
|
||||
/* Deny: wants 8.0, only 7.0 of headroom remains (10.0 - 3.0). */
|
||||
xvec_init(&uncomitted_n, 1, sizeof(float));
|
||||
xvec_idval_init(&wanted_n, 1);
|
||||
xvec_idval_store(&wanted_n, 0, 8.0f);
|
||||
xvec_init(&uncomitted_s, 1, sizeof(float));
|
||||
xvec_idval_init(&wanted_s, 1);
|
||||
xvec_idval_store(&wanted_s, 0, 8.0f);
|
||||
|
||||
rc_normal = sched_check_shared_satisfy(core_normal, &uncomitted_n,
|
||||
&wanted_n, &unmeet_n);
|
||||
rc_sim = sched_check_shared_satisfy(core_sim, &uncomitted_s,
|
||||
&wanted_s, &unmeet_s);
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(0, rc_normal);
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(
|
||||
rc_normal, rc_sim,
|
||||
"sched_check_shared_satisfy() must deny identically for a "
|
||||
"normal-mode-shaped and a simulation-mode-shaped core");
|
||||
|
||||
xvec_fini(&uncomitted_n);
|
||||
xvec_idval_fini(&wanted_n);
|
||||
xvec_idval_fini(&unmeet_n);
|
||||
xvec_fini(&uncomitted_s);
|
||||
xvec_idval_fini(&wanted_s);
|
||||
xvec_idval_fini(&unmeet_s);
|
||||
|
||||
zarray_fini(&core_normal->sharedInst);
|
||||
zarray_fini(&core_normal->sharedInUse);
|
||||
zarray_fini(&core_sim->sharedInst);
|
||||
zarray_fini(&core_sim->sharedInUse);
|
||||
}
|
||||
|
||||
/* --- sched_check_host_satisfy(): identical grant/deny --------------- */
|
||||
{
|
||||
xce_sched_worker_t w_normal, w_sim;
|
||||
xvec_t uncomitted_n, uncomitted_s;
|
||||
xvec_idval_t wanted_n, wanted_s, unmeet_n, unmeet_s;
|
||||
xce_val_t total, inuse;
|
||||
int rc_normal, rc_sim;
|
||||
|
||||
memset(&w_normal, 0, sizeof(w_normal));
|
||||
memset(&w_sim, 0, sizeof(w_sim));
|
||||
zarray_init(&w_normal.resvals, 4, NULL);
|
||||
zarray_init(&w_normal.resInUse, 4, NULL);
|
||||
zarray_init(&w_sim.resvals, 4, NULL);
|
||||
zarray_init(&w_sim.resInUse, 4, NULL);
|
||||
|
||||
memset(&total, 0, sizeof(total));
|
||||
total.which = Value_u_fvalue;
|
||||
total.u.fvalue = 10.0f;
|
||||
memset(&inuse, 0, sizeof(inuse));
|
||||
inuse.which = Value_u_fvalue;
|
||||
inuse.u.fvalue = 3.0f;
|
||||
|
||||
zarray_put(&w_normal.resvals, 0, &total);
|
||||
zarray_put(&w_normal.resInUse, 0, &inuse);
|
||||
zarray_put(&w_sim.resvals, 0, &total);
|
||||
zarray_put(&w_sim.resInUse, 0, &inuse);
|
||||
|
||||
/* Grant */
|
||||
xvec_init(&uncomitted_n, 1, sizeof(float));
|
||||
xvec_idval_init(&wanted_n, 1);
|
||||
xvec_idval_store(&wanted_n, 0, 5.0f);
|
||||
xvec_init(&uncomitted_s, 1, sizeof(float));
|
||||
xvec_idval_init(&wanted_s, 1);
|
||||
xvec_idval_store(&wanted_s, 0, 5.0f);
|
||||
|
||||
rc_normal = sched_check_host_satisfy(core_normal, &w_normal,
|
||||
&uncomitted_n, &wanted_n,
|
||||
&unmeet_n);
|
||||
rc_sim = sched_check_host_satisfy(core_sim, &w_sim, &uncomitted_s,
|
||||
&wanted_s, &unmeet_s);
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(1, rc_normal);
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(
|
||||
rc_normal, rc_sim,
|
||||
"sched_check_host_satisfy() must grant identically for a "
|
||||
"normal-mode-shaped and a simulation-mode-shaped core");
|
||||
|
||||
xvec_fini(&uncomitted_n);
|
||||
xvec_idval_fini(&wanted_n);
|
||||
xvec_idval_fini(&unmeet_n);
|
||||
xvec_fini(&uncomitted_s);
|
||||
xvec_idval_fini(&wanted_s);
|
||||
xvec_idval_fini(&unmeet_s);
|
||||
|
||||
/* Deny */
|
||||
xvec_init(&uncomitted_n, 1, sizeof(float));
|
||||
xvec_idval_init(&wanted_n, 1);
|
||||
xvec_idval_store(&wanted_n, 0, 8.0f);
|
||||
xvec_init(&uncomitted_s, 1, sizeof(float));
|
||||
xvec_idval_init(&wanted_s, 1);
|
||||
xvec_idval_store(&wanted_s, 0, 8.0f);
|
||||
|
||||
rc_normal = sched_check_host_satisfy(core_normal, &w_normal,
|
||||
&uncomitted_n, &wanted_n,
|
||||
&unmeet_n);
|
||||
rc_sim = sched_check_host_satisfy(core_sim, &w_sim, &uncomitted_s,
|
||||
&wanted_s, &unmeet_s);
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(0, rc_normal);
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(
|
||||
rc_normal, rc_sim,
|
||||
"sched_check_host_satisfy() must deny identically for a "
|
||||
"normal-mode-shaped and a simulation-mode-shaped core");
|
||||
|
||||
xvec_fini(&uncomitted_n);
|
||||
xvec_idval_fini(&wanted_n);
|
||||
xvec_idval_fini(&unmeet_n);
|
||||
xvec_fini(&uncomitted_s);
|
||||
xvec_idval_fini(&wanted_s);
|
||||
xvec_idval_fini(&unmeet_s);
|
||||
|
||||
zarray_fini(&w_normal.resvals);
|
||||
zarray_fini(&w_normal.resInUse);
|
||||
zarray_fini(&w_sim.resvals);
|
||||
zarray_fini(&w_sim.resInUse);
|
||||
}
|
||||
|
||||
destroy(core_normal->resmgr);
|
||||
destroy(core_sim->resmgr);
|
||||
}
|
||||
|
||||
#define TEST(x) \
|
||||
do { \
|
||||
if (check_test(&arguments, #x)) { \
|
||||
|
|
@ -505,6 +753,7 @@ int main(int argc, char* argv[])
|
|||
TEST(test_new_sched_op_enum_values_exist);
|
||||
TEST(test_sched_update_existing_queue_null_payload);
|
||||
TEST(test_dead_pushmsg_symbols_absent);
|
||||
TEST(test_core_safe_allocation_chain_driver_parity);
|
||||
|
||||
return UNITY_END();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -136,19 +136,22 @@ int __wrap_xcecli_join(xcecli_ctx_t c, int role, hostattrs_t* attrs)
|
|||
* the decisive "did the real allocator run" signal.
|
||||
* ════════════════════════════════════════════════════════════════════════ */
|
||||
|
||||
extern int __real_sched_meet_host_selection(xce_scheduler_t*,
|
||||
/* scheduler-sim-live-allocation task 1.3: sched_meet_host_selection() is
|
||||
* now core-typed (xce_sched_core_t*, not xce_scheduler_t*) -- the linker
|
||||
* --wrap= interposition must match the real symbol's current signature. */
|
||||
extern int __real_sched_meet_host_selection(xce_sched_core_t*,
|
||||
xce_sched_worker_t*,
|
||||
xce_select_t*);
|
||||
|
||||
static int g_select_calls = 0;
|
||||
|
||||
int __wrap_sched_meet_host_selection(xce_scheduler_t* sched,
|
||||
int __wrap_sched_meet_host_selection(xce_sched_core_t* core,
|
||||
xce_sched_worker_t* w,
|
||||
xce_select_t* select)
|
||||
{
|
||||
g_select_calls++;
|
||||
|
||||
return __real_sched_meet_host_selection(sched, w, select);
|
||||
return __real_sched_meet_host_selection(core, w, select);
|
||||
}
|
||||
|
||||
void setUp(void) { return; }
|
||||
|
|
|
|||
|
|
@ -101,19 +101,22 @@ int __wrap_xcecli_join(xcecli_ctx_t c, int role, hostattrs_t* attrs)
|
|||
* identical wrap for rationale.
|
||||
* ════════════════════════════════════════════════════════════════════════ */
|
||||
|
||||
extern int __real_sched_meet_host_selection(xce_scheduler_t*,
|
||||
/* scheduler-sim-live-allocation task 1.3: sched_meet_host_selection() is
|
||||
* now core-typed (xce_sched_core_t*, not xce_scheduler_t*) -- the linker
|
||||
* --wrap= interposition must match the real symbol's current signature. */
|
||||
extern int __real_sched_meet_host_selection(xce_sched_core_t*,
|
||||
xce_sched_worker_t*,
|
||||
xce_select_t*);
|
||||
|
||||
static int g_select_calls = 0;
|
||||
|
||||
int __wrap_sched_meet_host_selection(xce_scheduler_t* sched,
|
||||
int __wrap_sched_meet_host_selection(xce_sched_core_t* core,
|
||||
xce_sched_worker_t* w,
|
||||
xce_select_t* select)
|
||||
{
|
||||
g_select_calls++;
|
||||
|
||||
return __real_sched_meet_host_selection(sched, w, select);
|
||||
return __real_sched_meet_host_selection(core, w, select);
|
||||
}
|
||||
|
||||
void setUp(void) { return; }
|
||||
|
|
|
|||
|
|
@ -815,7 +815,7 @@ static void* capacity_aware_allocator_thread_fn(void* arg)
|
|||
rc = xvec_idval_store(&wanted, g_slots_residx_normal, want);
|
||||
TEST_ASSERT_TRUE(rc >= 0);
|
||||
|
||||
rc = sched_check_host_satisfy(sched, w, &uncomitted, &wanted, &unmeet);
|
||||
rc = sched_check_host_satisfy(core, w, &uncomitted, &wanted, &unmeet);
|
||||
|
||||
xvec_fini(&uncomitted);
|
||||
xvec_idval_fini(&wanted);
|
||||
|
|
@ -1404,7 +1404,7 @@ test_contention_parity_matches_real_normal_mode_recording_round_by_round(
|
|||
rc = xvec_idval_store(&wanted, residx_normal, JOBB_WANT);
|
||||
TEST_ASSERT_TRUE(rc >= 0);
|
||||
|
||||
rc = sched_check_host_satisfy(&sched, w_normal, &uncomitted, &wanted,
|
||||
rc = sched_check_host_satisfy(&(sched.core), w_normal, &uncomitted, &wanted,
|
||||
&unmeet);
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(
|
||||
0, rc,
|
||||
|
|
@ -1425,7 +1425,7 @@ test_contention_parity_matches_real_normal_mode_recording_round_by_round(
|
|||
rc = xvec_idval_store(&wanted, residx_sim, JOBB_WANT);
|
||||
TEST_ASSERT_TRUE(rc >= 0);
|
||||
|
||||
rc = sched_check_host_satisfy(&wrapper_sim, w_sim, &uncomitted,
|
||||
rc = sched_check_host_satisfy(&(wrapper_sim.core), w_sim, &uncomitted,
|
||||
&wanted, &unmeet);
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(
|
||||
0, rc,
|
||||
|
|
@ -1661,7 +1661,7 @@ static int check_host_satisfy_want(xce_sched_sim_driver_t* sim, float want)
|
|||
rc = xvec_idval_store(&wanted, residx, want);
|
||||
TEST_ASSERT_TRUE(rc >= 0);
|
||||
|
||||
rc = sched_check_host_satisfy(&wrapper, w, &uncomitted, &wanted, &unmeet);
|
||||
rc = sched_check_host_satisfy(&(wrapper.core), w, &uncomitted, &wanted, &unmeet);
|
||||
|
||||
xvec_fini(&uncomitted);
|
||||
xvec_idval_fini(&wanted);
|
||||
|
|
|
|||
|
|
@ -826,7 +826,9 @@ static xce_decision_t* decide_one_candidate(xce_scheduler_t* sched,
|
|||
rc = xvec_idval_store(&wanted, g_slots_residx, want);
|
||||
TEST_ASSERT_TRUE(rc >= 0);
|
||||
|
||||
rc = sched_check_host_satisfy(sched, w, &uncomitted, &wanted, &unmeet);
|
||||
/* scheduler-sim-live-allocation task 1.3: sched_check_host_satisfy()
|
||||
* is now core-typed -- pass the already-derived `core` local. */
|
||||
rc = sched_check_host_satisfy(core, w, &uncomitted, &wanted, &unmeet);
|
||||
|
||||
xvec_fini(&uncomitted);
|
||||
xvec_idval_fini(&wanted);
|
||||
|
|
@ -915,7 +917,9 @@ static void* preexist_prelude_allocator_thread_fn(void* arg)
|
|||
rc = xvec_idval_store(&wanted, g_slots_residx, PREEXIST_WANT);
|
||||
TEST_ASSERT_TRUE(rc >= 0);
|
||||
|
||||
rc = sched_check_host_satisfy(sched, w2, &uncomitted, &wanted, &unmeet);
|
||||
/* task 1.3: sched_check_host_satisfy() is now core-typed -- pass
|
||||
* the already-derived `core` local. */
|
||||
rc = sched_check_host_satisfy(core, w2, &uncomitted, &wanted, &unmeet);
|
||||
|
||||
xvec_fini(&uncomitted);
|
||||
xvec_idval_fini(&wanted);
|
||||
|
|
|
|||
|
|
@ -661,7 +661,10 @@ static void* capacity_aware_allocator_thread_fn(void* arg)
|
|||
rc = xvec_idval_store(&wanted, SLOTS_RESIDX, want);
|
||||
TEST_ASSERT_TRUE(rc >= 0);
|
||||
|
||||
rc = sched_check_host_satisfy(sched, w, &uncomitted, &wanted, &unmeet);
|
||||
/* scheduler-sim-live-allocation task 1.3: sched_check_host_
|
||||
* satisfy() is now core-typed -- pass the already-derived `core`
|
||||
* local. */
|
||||
rc = sched_check_host_satisfy(core, w, &uncomitted, &wanted, &unmeet);
|
||||
|
||||
xvec_fini(&uncomitted);
|
||||
xvec_idval_fini(&wanted);
|
||||
|
|
|
|||
|
|
@ -764,7 +764,7 @@ test_reconciled_job_charges_resinuse_before_live_capacity_check(void)
|
|||
rc = xvec_idval_store(&wanted, residx, 5.0f); /* > 2.0 remaining */
|
||||
TEST_ASSERT_TRUE(rc >= 0);
|
||||
|
||||
rc = sched_check_host_satisfy(&wrapper, w, &uncomitted, &wanted, &unmeet);
|
||||
rc = sched_check_host_satisfy(&(wrapper.core), w, &uncomitted, &wanted, &unmeet);
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(
|
||||
0, rc,
|
||||
"a job wanting more than the 2.0-unit remaining headroom must be "
|
||||
|
|
@ -782,7 +782,7 @@ test_reconciled_job_charges_resinuse_before_live_capacity_check(void)
|
|||
rc = xvec_idval_store(&wanted, residx, 2.0f); /* == 2.0 remaining, exact fit */
|
||||
TEST_ASSERT_TRUE(rc >= 0);
|
||||
|
||||
rc = sched_check_host_satisfy(&wrapper, w, &uncomitted, &wanted, &unmeet);
|
||||
rc = sched_check_host_satisfy(&(wrapper.core), w, &uncomitted, &wanted, &unmeet);
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(
|
||||
1, rc,
|
||||
"a job wanting exactly the 2.0-unit remaining headroom must be "
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue