fix(scheduler): sim resource over-commit, byte-unit display, sync job-state-at-capture
- bug-1799/1801: fix resInUse over-commit in sim replay -- sched_account_jobs's per-round re-derive pass now skips RECONCILING/UNAVAIL workers the same way core_reset_workers already does (bug-1751), closing the gap that let a worker's used slots exceed its own capacity across a resync replay - bug-1804: revise scheduler-sim-eager-reconciliation spec (user-directed) so a captured job's job->state is set to RUN synchronously at dispatch capture, mirroring sched_commit_decision's normal-mode semantics (bug-1624), instead of deferring until its separately-recorded JOB_STATE_CHANGE event replays - bug-1800: render bytes-valued CONSUMABLE resources (mem/swp/tmp) with the same human-scaled unit formatting already used for maxmem/maxswap/maxtmp - bug-1802/1803: add then revert a break-on-ANY-event breakpoint kind after live feedback that it over-fires inside busy sessions; replace it with a prescan-based "next non-dummy session" hint in info summary instead Full scheduler suite: 77/77 tests pass (asan profile). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
This commit is contained in:
parent
ffca959ed9
commit
25fb5c115a
22 changed files with 1827 additions and 303 deletions
|
|
@ -369,6 +369,86 @@ static void test_commit_job_alloc_identical_across_core_containers(void)
|
|||
TEST_ASSERT_EQUAL_FLOAT(shared_sched[0], shared_sim[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
* test_charge_account_skips_reconciling_or_unavail_worker_host_charge -
|
||||
* bug-1799 fix: sched_charge_account()'s per-host resInUse charge must be
|
||||
* skipped for a worker currently IS_WORKER_RECONCILING or IS_WORKER_UNAVAIL.
|
||||
* core_reset_workers() (core_session.c, bug-1751) already skips RESETTING
|
||||
* such a worker's resInUse every round; sched_account_jobs()'s own
|
||||
* per-round re-derive pass reaches resInUse only through this same
|
||||
* sched_charge_account()->sched_update_account() path, so without a
|
||||
* matching skip here it re-added a full charge ON TOP of the not-reset
|
||||
* total every round the worker stayed RECONCILING/UNAVAIL -- resInUse grew
|
||||
* unboundedly and could exceed the resource's real capacity (live-observed:
|
||||
* a 22-slot worker showing used=26.00). core->sharedInUse has no
|
||||
* per-worker gating at all (its own reset, core_reset_shared_resval(), is
|
||||
* unconditional) and must keep charging normally regardless of any one
|
||||
* host's status.
|
||||
*/
|
||||
static void
|
||||
test_charge_account_skips_reconciling_or_unavail_worker_host_charge(void)
|
||||
{
|
||||
xce_scheduler_t sched;
|
||||
xce_job_account_t* acct;
|
||||
xce_sched_worker_t* w;
|
||||
float shared_val[1];
|
||||
float host_val[1];
|
||||
int shared_idx[1] = { SHARED_RESIDX };
|
||||
int host_idx[1] = { HOST_RESIDX };
|
||||
int rc;
|
||||
|
||||
memset(&sched, 0, sizeof(sched));
|
||||
setup_core_with_worker(&(sched.core), WORKER_NAME);
|
||||
|
||||
w = sched_get_worker(&(sched.core), WORKER_NAME);
|
||||
TEST_ASSERT_NOT_NULL(w);
|
||||
|
||||
acct = make_test_account(WORKER_NAME, SHARED_RESIDX, SHARED_USED,
|
||||
SHARED_RESERVED, HOST_RESIDX, HOST_USED,
|
||||
HOST_RESERVED);
|
||||
|
||||
/* --- RECONCILING: shared charges normally, per-host charge skipped --- */
|
||||
w->status = XCE_WORKER_RECONCILING;
|
||||
rc = sched_charge_account(&(sched.core), acct);
|
||||
TEST_ASSERT_EQUAL_INT(0, rc);
|
||||
|
||||
get_resvals(&(sched.core.sharedInUse), 1, shared_idx, shared_val);
|
||||
TEST_ASSERT_EQUAL_FLOAT_MESSAGE(
|
||||
EXPECTED_SHARED_CHARGE, shared_val[0],
|
||||
"shared resources have no per-worker gating and must still charge "
|
||||
"while the host is RECONCILING");
|
||||
|
||||
get_resvals(&(w->resInUse), 1, host_idx, host_val);
|
||||
TEST_ASSERT_EQUAL_FLOAT_MESSAGE(
|
||||
0.0f, host_val[0],
|
||||
"bug-1799: a RECONCILING worker's per-host resInUse must NOT be "
|
||||
"charged -- core_reset_workers() already skips resetting it, so "
|
||||
"charging on top would grow it every round it stays RECONCILING");
|
||||
|
||||
/* --- UNAVAIL: same per-host skip --- */
|
||||
w->status = XCE_WORKER_UNAVAIL;
|
||||
rc = sched_charge_account(&(sched.core), acct);
|
||||
TEST_ASSERT_EQUAL_INT(0, rc);
|
||||
|
||||
get_resvals(&(w->resInUse), 1, host_idx, host_val);
|
||||
TEST_ASSERT_EQUAL_FLOAT_MESSAGE(
|
||||
0.0f, host_val[0],
|
||||
"bug-1799: an UNAVAIL worker's per-host resInUse must NOT be "
|
||||
"charged either -- the same reset-skip condition covers both bits");
|
||||
|
||||
/* --- status clears: normal charging resumes on the very next call --- */
|
||||
w->status = 0;
|
||||
rc = sched_charge_account(&(sched.core), acct);
|
||||
TEST_ASSERT_EQUAL_INT(0, rc);
|
||||
|
||||
get_resvals(&(w->resInUse), 1, host_idx, host_val);
|
||||
TEST_ASSERT_EQUAL_FLOAT_MESSAGE(
|
||||
EXPECTED_HOST_CHARGE, host_val[0],
|
||||
"once the worker's status bit clears, charging must resume "
|
||||
"normally on the very next call -- this is a per-call skip, not a "
|
||||
"permanent block");
|
||||
}
|
||||
|
||||
/*
|
||||
* resource-accounting.md's reservation-vs-actual-usage reconciliation for
|
||||
* a REAL (gauge-style) resource, e.g. "mem" -- sched_reconcile_host_
|
||||
|
|
@ -1142,6 +1222,7 @@ int main(void)
|
|||
UNITY_BEGIN();
|
||||
RUN_TEST(test_charge_account_identical_across_core_containers);
|
||||
RUN_TEST(test_commit_job_alloc_identical_across_core_containers);
|
||||
RUN_TEST(test_charge_account_skips_reconciling_or_unavail_worker_host_charge);
|
||||
RUN_TEST(
|
||||
test_reconcile_host_resource_usage_below_reservation_keeps_reservation);
|
||||
RUN_TEST(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue