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:
Rongsong Shen 2026-09-12 14:06:41 +00:00
parent ffca959ed9
commit 25fb5c115a
No known key found for this signature in database
GPG key ID: 5BCDAAE0123E9FE2
22 changed files with 1827 additions and 303 deletions

View file

@ -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(