fix(scheduler-sim-diagnostics): bootstrap limit plugin in sim mode (bug-1825)

info limit was correctly implemented and tested but inert against a real
replay: register_limit()'s only call site was normal-mode sched_register_
plugins(); sim mode's own plugin bootstrap (sim_bootstrap_picker()) never
registered the limit plugin. The snapshot format already carries the
original session's limit config (sim->core.config, a borrowed reference set
by xce_sched_core_load_snapshot()) -- nothing needed to change in the
recording/replay format.

New sim_bootstrap_limit_plugin() (sim_limit.c, mirroring sim_picker.c's
structure) registers the plugin via plugin_register_core() and seeds it via
a new limit_seed_config(plugin, xce_sched_core_t* core, config) entry point,
wired into sim_loop.c alongside the existing sim_bootstrap_picker() call.
limit_new_plugin() extracted from register_limit() as a factory, mirroring
builtin_fcfs_new_plugin()'s established pattern; register_limit() itself is
behavior-preserving.

First attempt set plugin->sched to a disguised xce_sched_sim_driver_t*,
relying on it sharing xce_scheduler_t's first-member layout to reuse the
existing config_hook path -- rejected on review: this repeats the exact
cross-cast pattern that already corrupted memory once in this codebase (see
core.h's xce_core_cache_clear_cb_t history). Fixed by making
limit_seed_config() take xce_sched_core_t* as an honest parameter instead,
with limit_update_config() (normal mode) and the new sim path both
delegating to a shared limit_seed_config_impl() -- no cast, no aliasing risk,
independently verified by two review rounds reading the actual struct
layouts and call chains.

Also added sim_limit.c to sched_sim_isolation_lib so Req 5 AC 17's
controller-I/O-isolation check covers it (an initial gap, closed in the same
remediation round). Two ripple waves of the same established link-stub
pattern applied to the ~24 white-box test files that #include sim_loop.c.

info limit now shows real configured-limit data against a genuine replay.
Live usage will still correctly show "no active usage instance yet" until a
separate, larger fix (logged as bug-1826) wires limit *matching* into the
sim decision path -- deliberately out of this task's scope.

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-18 04:46:49 +00:00
parent 2f1ffd1e4a
commit 487e7b9419
No known key found for this signature in database
GPG key ID: 5BCDAAE0123E9FE2
32 changed files with 1377 additions and 28 deletions

View file

@ -8,7 +8,7 @@
- _Requirements: 1.1, 1.2, 1.4, 2.1, 3.1_
- _Boundary: Limit Plugin Accessor_
- [ ] 6. Bootstrap the limit plugin in sim mode so `info limit` shows real data against a replay (fixes `bug-1825`)
- [x] 6. Bootstrap the limit plugin in sim mode so `info limit` shows real data against a replay (fixes `bug-1825`)
- Extract `limit_new_plugin()` factory out of `register_limit()` (`plugins/limit.c`), mirroring `builtin_fcfs_new_plugin()`/`register_builtin_fcfs()`'s existing factory-extraction pattern exactly; `register_limit()` itself must be behaviorally unchanged (pure refactor)
- New `sim_bootstrap_limit_plugin(xce_sched_sim_driver_t* sim)` (new file `sim_limit.c`, mirroring `sim_picker.c`'s structure/header-comment convention): `limit_new_plugin()` → `plugin_register_core(&(sim->core), plugin)` → if `sim->core.config != NULL`, call `plugin->hooks.config_hook(plugin, sim->core.config)` directly (NOT the type-unsafe `plugin_config_update()`, which casts its `void*` arg to `xce_scheduler_t*` and would misread `xce_sched_sim_driver_t`'s embedded `core` field)
- Wire the call into `sim_loop.c` right alongside the existing `sim_bootstrap_picker(sim)` call site — by that point `sim->core.config` already holds the snapshot's borrowed-reference config (set during `sched_sim_driver_start()`'s snapshot load, which runs first)
@ -76,4 +76,5 @@ No `(P)` markers are used anywhere in this plan. Tasks 2.1–2.3 and 3.1–3.2 a
- **Task 2.1**: Making `repl_info.c` genuinely call `limit_get_configured_limits()` broke the link for ~24 pre-existing white-box test files that `#include "../src/repl_info.c"` without also linking `plugins/limit.c` — this codebase's white-box test convention means any new cross-file call from an included production file ripples to every file that includes the caller but not the callee. Fixed with an identical 5-line link-satisfying stub (`return NULL`) added to each, matching the established "duplicate, don't share" stub idiom already used throughout this file family; verified behavior-preserving since none of those 24 fixtures register the limit plugin (the real function would also return `NULL` there). **Task 3 (which calls `limit_get_usage_instances()`) will very likely hit the identical ripple across an overlapping or identical file set — expect it, and apply the same fix pattern rather than treating it as a surprise.**
- **Task 3.1**: found and fixed a real latent bounds-check imprecision (negative/stale `idx` not safely rejected by a `.count`-based pre-check) while writing the new GLOBAL/SHARED usage-read code — logged as `bug-1824` in `.wolf/buglog.json` rather than fixed in the pre-existing `repl_info_resource_one()` (out of this task's boundary); the new code uses the corrected pattern instead. Task 3.2 confirmed it did NOT repeat the same mistake in its own per-host reads.
- **Task 3.2**: reviewer approved with one non-blocking suggestion — no test directly exercises Requirement 3.1's "per-user and per-host together" combined-dimension case end-to-end (structurally supported by the code, per independent review inspection, just not covered by a dedicated fixture). Worth adding if this area gets touched again; not required before shipping.
- **Task 5 — significant follow-up needed (logged as `bug-1825`)**: all 5 tasks are correctly implemented, thoroughly tested, and genuinely read-only/deterministic — but `info limit` is currently **inert in real production usage**. `register_limit()` has exactly one call site in the whole codebase (`scheduler.c`'s normal-mode `sched_register_plugins()`); sim mode's own plugin bootstrap (`sim_bootstrap_picker()`, `sim_picker.c`) only registers the picker plugin, never the limit plugin. So a real operator running `xce_scheduler -i`/`-s <replay>` will always see "no limits configured"/"no such limit" from `info limit`, regardless of what the original live recording had configured — every positive-display test in this spec exercises the code via a test-only plugin-registration helper with no production equivalent in sim mode. This is a pre-existing sim-mode driver gap (same class as `scheduler-driver-equivalence.md`'s other documented normal-vs-sim parity gaps), not a defect in this spec's own work, and was out of task 5's test-only boundary to fix. **Recommended as the next piece of work for this open-ended spec** (or a small companion fix): add a sim-mode limit-plugin bootstrap analogous to `sim_bootstrap_picker()`, and confirm `.replay` files actually carry the original limit configuration for such a bootstrap to register from (not yet verified — check this first).
- **Task 5 — significant follow-up needed (logged as `bug-1825`)**: all 5 tasks are correctly implemented, thoroughly tested, and genuinely read-only/deterministic — but `info limit` is currently **inert in real production usage**. `register_limit()` has exactly one call site in the whole codebase (`scheduler.c`'s normal-mode `sched_register_plugins()`); sim mode's own plugin bootstrap (`sim_bootstrap_picker()`, `sim_picker.c`) only registers the picker plugin, never the limit plugin. So a real operator running `xce_scheduler -i`/`-s <replay>` will always see "no limits configured"/"no such limit" from `info limit`, regardless of what the original live recording had configured — every positive-display test in this spec exercises the code via a test-only plugin-registration helper with no production equivalent in sim mode. This is a pre-existing sim-mode driver gap (same class as `scheduler-driver-equivalence.md`'s other documented normal-vs-sim parity gaps), not a defect in this spec's own work, and was out of task 5's test-only boundary to fix. Fixed by task 6.
- **Task 6 — a real memory-safety lesson, caught by review before it shipped**: the first implementation attempt set `plugin->sched = (void*)sim` (a `xce_sched_sim_driver_t*`, disguised) before invoking the limit plugin's `config_hook`, relying on both `xce_scheduler_t` and `xce_sched_sim_driver_t` happening to have `xce_sched_core_t core` as their first struct member. An independent reviewer rejected this: `core.h`'s own `xce_core_cache_clear_cb_t` doc comment documents that this EXACT cross-cast pattern already corrupted memory once before in this codebase (`cache_clear()` reinterpreting `xce_sched_sim_driver_t`'s `alt_events_file` as a `kvtab_t*`), and there was no compiler/runtime guard against a future edit to the callee reading past `.core`. Fixed by adding `limit_seed_config(plugin, xce_sched_core_t* core, config)` — an honestly-typed entry point taking `core` as a real field access, no cast — with `limit_update_config()` (normal mode) and `sim_bootstrap_limit_plugin()` (sim mode) both delegating to a shared `_impl` function. **Lesson for future work in this codebase**: when a plugin hook or helper is invoked from BOTH a normal-mode (`xce_scheduler_t`) and a sim-mode (`xce_sched_sim_driver_t`) context, never derive one struct type from the other via a first-member cast, even when it "happens to work" today — take `xce_sched_core_t*` as an honest parameter instead. Two independent reviewers (one per round) verified this by reading the actual struct definitions and the full call chain, not by trusting the report.

View file

@ -22428,7 +22428,7 @@
"error_message": "NOT A CRASH -- significant, verified architectural gap discovered while closing out scheduler-sim-diagnostics task 5 (final validation task for the new `info limit` REPL command). The limit plugin is never registered in ANY simulation-mode driver path, so `info limit <name|all>` will ALWAYS report \"no limits configured\"/\"no such limit\" for a real operator running `xce_scheduler -i`/`-s <replay>` against a genuine recording -- even one whose original live run had limits configured and actively enforced. The entire feature built across scheduler-sim-diagnostics tasks 1-5 is correctly implemented, thoroughly tested, and read-only/deterministic as designed, but is currently INERT in real production usage: every positive-display test path (tasks 2-3, showing a limit's configured setting and live usage) only exercises the code via a test-only helper that hand-registers the plugin into core->plugins directly, which has no production equivalent in sim mode.",
"file": "src/scheduler/src/sim_picker.c",
"root_cause": "register_limit() (plugins/limit.c:609) has exactly one call site in the entire codebase: scheduler.c:605, inside sched_register_plugins(), which is itself called only from scheduler.c:827 -- the normal-mode (controller-connected, live) driver's sched_init() path. Sim mode's own plugin-bootstrap mechanism, sim_bootstrap_picker() (sim_picker.c), exists specifically to register a picker plugin (builtin_fcfs, via plugin_register_core()) for simulation/replay mode, since sim mode deliberately does not run the full normal-mode init sequence -- but it only ever registers the PICKER plugin category. It has no equivalent step for the limit plugin (or, by the same reasoning, potentially other plugin categories registered by sched_register_plugins() that were never audited for this gap). Confirmed via full-codebase grep: register_limit()/sched_register_plugins() are never referenced anywhere under sim.c/sim_loop.c/sim_picker.c/driver.c/repl*.c, and no write into core->plugins occurs anywhere in the sim-mode driver files. This is the same class of gap scheduler-driver-equivalence.md already documents for OTHER driver-parity properties (e.g. bug-1613's sched_account_jobs() gap) -- a sim-mode driver feature silently missing something the normal-mode driver does, discovered only when a REPL feature tried to read state that assumes it.",
"fix": "NOT FIXED -- discovered and characterized during scheduler-sim-diagnostics task 5 (final validation task), explicitly out of that task's test-only boundary per its own instructions (a production-code fix found during validation must be reported, not silently patched). Recommended fix: add a sim-mode limit-plugin bootstrap analogous to sim_bootstrap_picker() -- either a new sim_bootstrap_limit_plugin() called from the same place sim_bootstrap_picker() is invoked (sim_loop.c, per that function's own doc comment), or generalize sched_register_plugins() itself to be safely callable from sim mode (auditing whether builtin_fcfs's own registration would double-register if sim_bootstrap_picker() and sched_register_plugins() both ran). Needs a decision on whether the sim driver should register ALL production plugin categories (matching normal mode exactly, closing this gap generally) or add limit-specific bootstrap only (narrower, faster, but leaves the general problem for the next plugin type that needs sim-mode REPL visibility). Also needs the actual config source: sim mode's replay files must carry the original limit configuration if there is to be anything for a bootstrap step to register from -- confirm whether `.replay` files / ReplaySession already embed limit config, or whether that itself is a second, sequential gap. This second question was not investigated in this session -- flagged as the first thing a fix attempt needs to check.",
"fix": "FIXED (2026-09-17, scheduler-sim-diagnostics task 6). Added limit_new_plugin() factory (extracted from register_limit(), mirroring builtin_fcfs_new_plugin()'s established pattern) and a new sim_bootstrap_limit_plugin() (new file src/scheduler/src/sim_limit.c, mirroring sim_picker.c's structure exactly): registers the limit plugin via plugin_register_core() and seeds it with sim->core.config (the snapshot's own borrowed-reference config, which already carries the original session's limit configuration -- no recording/replay format change needed) via a new limit_seed_config(plugin, xce_sched_core_t* core, config) entry point. Wired into sim_loop.c alongside the existing sim_bootstrap_picker(sim) call.\n\nFirst attempt (round 1) set plugin->sched = (void*)sim (a disguised xce_sched_sim_driver_t*) to reuse the existing config_hook path -- REJECTED on independent review: this repeats the exact pointer-to-first-member cross-cast pattern that already corrupted memory once in this codebase (see this bug's own root_cause note and core.h's xce_core_cache_clear_cb_t doc comment for that prior incident). Round 2 eliminated the cast entirely: limit_seed_config() takes xce_sched_core_t* core as an honest parameter (a real field both xce_scheduler_t and xce_sched_sim_driver_t genuinely have), delegating to a shared limit_seed_config_impl() also used by normal-mode limit_update_config(). No cast, no aliasing risk -- confirmed structurally sound by two independent reviewers, each reading the actual struct definitions and full call chain rather than trusting the report.\n\nAlso closed: sim_limit.c added to sched_sim_isolation_lib's source list (meson.build) so Req 5 AC 17's mechanical controller-I/O-isolation check covers it (round 1 omitted this; round 2 fixed it, sched_sim_isolation_test independently re-verified passing with the new file included).\n\nRipple: two waves of an identical, minimal link-satisfying stub pattern across the ~24 white-box test files that #include \"../src/sim_loop.c\" (one for limit_new_plugin(), one for limit_seed_config()) -- same established 'duplicate, don't share' idiom this file family already used for the earlier scheduler-sim-diagnostics tasks' repl_info.c ripple.\n\nTDD: RED->GREEN verified for both the config-seed test and the remediation itself (a temporary limit_seed_config() no-op stub reproduced the exact expected single-test failure, reverted cleanly). Full scheduler suite: 78/78 Ok, 0 Fail; sched_repl_limit_table_test 26/26; sched_limit_plugin_test 5/5 (zero regression to normal-mode registration); sched_sim_isolation_test 5/5 (genuinely covering the new file).\n\nDeliberately NOT fixed (separate, larger, tracked as a distinct follow-up item in .kiro/specs/scheduler-sim-diagnostics/tasks.md, not this bug): limit *matching* (limit_job_election()) is still never invoked during replay -- it's only reachable via plugin_job_election(), which is normal-mode-only (one caller, scheduler.c) and would itself need a core-safe variant before it could be wired into sim_loop.c's decision path. So 'info limit' now shows real CONFIGURED settings against a real replay, but live USAGE will still correctly show 'no active usage instance yet' until that separate, larger fix lands.",
"tags": [
"scheduler",
"sim-mode",
@ -22442,6 +22442,29 @@
],
"occurrences": 1,
"last_seen": "2026-09-17T07:10:00Z"
},
{
"id": "bug-1826",
"timestamp": "2026-09-17T21:50:00Z",
"error_message": "NOT A CRASH -- known, deliberately out-of-scope follow-up discovered while fixing bug-1825 (sim-mode limit plugin bootstrap, scheduler-sim-diagnostics task 6). Bug-1825's fix makes the limit plugin's CONFIGURED SETTING visible in sim mode (info limit now shows a real replay's actual limit configuration). But limit *matching* -- the mechanism that actually populates live usage instances (xce_vres_t) as jobs get evaluated -- is still never invoked during replay. So info limit's live-usage display will correctly show 'no active usage instance yet' for every limit against any real replay, even one whose original live session actively enforced and charged against that limit.",
"file": "src/scheduler/src/plugin.c",
"root_cause": "limit_job_election() (plugins/limit.c, the function that calls match_job_global_limit_()/match_job_host_limit_() and populates xce_vres_t usage instances) is only ever invoked via plugin_job_election() (plugin.c:554), which -- like plugin_config_update()/plugin_prepare_allocation() -- takes a `void* arg` cast unconditionally to `xce_scheduler_t*` and reads `sched->core.plugins`. plugin_job_election() has exactly ONE call site in the entire codebase: scheduler.c (normal-mode only). Nothing in sim_loop.c's replay decision path calls plugin_job_election() or any core-safe equivalent, so no limit ever gets matched against any job during simulation/replay, regardless of whether the limit plugin is registered (bug-1825 fixes registration+config, not this).",
"fix": "NOT FIXED -- deliberately deferred, tracked in `.kiro/specs/scheduler-sim-diagnostics/tasks.md`'s Implementation Notes as a known non-goal of task 6, not bundled into that task's scope. Fixing this properly needs: (1) a core-safe variant of plugin_job_election() (mirroring the plugin_register()/plugin_register_core() split bug-1825 already established for registration, and the limit_update_config()/limit_seed_config() split for config-seeding) that takes xce_sched_core_t* honestly instead of casting a void* to xce_scheduler_t*; (2) wiring a call to it into sim_loop.c's replay decision path, at whatever point a job becomes eligible for dispatch -- this touches the scheduler's most invariant-sensitive area (see .kiro/steering/scheduler-driver-equivalence.md's documented state-equivalence contract and its required resource-contention-fixture testing discipline, plus the known related gaps bug-1611/bug-1613 already track for other normal-vs-sim parity issues in this same decision path). This is a materially larger, higher-risk change than bug-1825's registration+config fix and should go through this project's full TDD + contention-fixture validation discipline, not be rushed in as a drive-by addition.",
"tags": [
"scheduler",
"sim-mode",
"repl",
"limit-plugin",
"limit-matching",
"plugin-job-election",
"architectural-gap",
"unfixed",
"discovered-during-scheduler-sim-diagnostics",
"driver-parity",
"follow-up-to-bug-1825"
],
"occurrences": 1,
"last_seen": "2026-09-17T21:50:00Z"
}
]
}

View file

@ -115,6 +115,40 @@ extern int register_fcfs(void*);
extern int register_builtin_fcfs(void*);
extern int register_limit(void*);
/*
* limit_new_plugin - factory half of register_limit()'s template-build
* step (plugins/limit.c), extracted so a caller with no xce_scheduler_t*
* (e.g. the simulation driver, via plugin_register_core() below) can
* obtain a freshly calloc'd, fully populated `xce_sched_plugin_t` for the
* limit plugin -- same hooks/init_fn/fini_fn template register_limit()
* itself uses, just not yet registered anywhere. Mirrors
* builtin_fcfs_new_plugin()'s identical extraction (below) exactly
* (scheduler-sim-diagnostics spec, task 6; bug-1825). Returns NULL on
* allocation failure. Caller owns the returned plugin (frees it only on a
* subsequent registration failure -- once registered, the plugin registry
* owns it, same lifetime rule every other plugin category in this
* codebase already follows).
*/
extern xce_sched_plugin_t* limit_new_plugin(void);
/*
* limit_seed_config - bug-1825 remediation round 2 (scheduler-sim-
* diagnostics spec, task 6): honestly-typed config-seed entry point for a
* caller that holds a real xce_sched_core_t* but no real xce_scheduler_t*
* -- the simulation driver (sim_limit.c's sim_bootstrap_limit_plugin()),
* whose xce_sched_sim_driver_t (sim.h) has no xce_scheduler_t to point
* plugin->sched at. Takes `core` directly with no cast and never touches
* plugin->sched -- see the function's own doc comment (plugins/limit.c)
* for why a plugin->sched type-pun is unsafe here (core.h's
* xce_core_cache_clear_cb_t doc comment documents the real production bug
* this avoids repeating). Delegates to the same seed logic
* limit_update_config() (the normal-mode config_hook) itself uses, so the
* two entry points cannot silently diverge in behavior.
*/
extern int limit_seed_config(xce_sched_plugin_t* plugin,
xce_sched_core_t* core,
xce_conf4sched_t* config);
/* limit_get_configured_limits/limit_get_usage_instances - scheduler-sim-
* diagnostics spec, Requirement Set 1 (Limit Plugin Accessor), task 1.
* Read-only crossing of the plugin-private-state boundary: each looks up

View file

@ -17,6 +17,7 @@ scheduler_srcs = [
'src/sim.c',
'src/sim_loop.c',
'src/sim_picker.c',
'src/sim_limit.c',
'src/sim_verify.c',
'src/sim_record.c',
'src/repl.c',
@ -100,32 +101,37 @@ sched_core_isolation_lib = static_library(
# the simulation driver's own files, consumed by
# testsuite/test_sim_isolation.c to prove at build time that
# sim.c/sim_loop.c/sim_record.c/repl.c/repl_fmt.c/repl_break.c/repl_info.c/
# repl_params.c/sim_picker.c reference zero controller-facing symbols
# (client/netio/xceapi/delay/idgen). All files are compiled together into
# ONE archive -- task 11.2 added sim_loop.c as a sibling file to task
# 11.1's sim.c, task 11.5 added sim_record.c as a third, task 12.1 added
# repl.c as a fourth, task 12.2 added repl_break.c/repl_info.c as a
# fifth/sixth (task 12.2's own 800-line-cap split of repl.c's
# repl_params.c/sim_picker.c/sim_limit.c reference zero controller-facing
# symbols (client/netio/xceapi/delay/idgen). All files are compiled
# together into ONE archive -- task 11.2 added sim_loop.c as a sibling
# file to task 11.1's sim.c, task 11.5 added sim_record.c as a third, task
# 12.1 added repl.c as a fourth, task 12.2 added repl_break.c/repl_info.c
# as a fifth/sixth (task 12.2's own 800-line-cap split of repl.c's
# breakpoint/state-inspection logic -- repl_internal.h's own "Why a split
# at all" section has the full rationale), task 12.3 added repl_params.c
# as a seventh (the same split, extended again for `snapshot`/`set`),
# bug-1567's fix added sim_picker.c as an eighth (sim_loop.c's own
# "zero line-budget headroom" -- same reason its siblings above exist --
# so the fix's picker-registration + post-load picker-rebuild-walk logic
# lives here instead of growing sim_loop.c past its cap), and the
# lives here instead of growing sim_loop.c past its cap), the
# scheduler-sim-repl-verbosity spec's task 7.2 remediation added repl_fmt.c
# as a ninth (repl.c's own 800-line-cap split of its shared, dependency-free
# formatting helpers -- repl_fmt.c's own header comment has the full
# rationale); covering only a subset of them would repeat core.c's own
# siblings' (core_events.c/core_session.c/core_clock.c)
# never-mechanically-covered gap for the sim driver. Same "compiling to an
# object is enough, no real linking needed" rationale as
# sched_core_isolation_lib above.
# rationale), and the scheduler-sim-diagnostics spec's task 6 (bug-1825
# fix, remediation round 2) added sim_limit.c as a tenth (sim_loop.c-cap
# sibling housing sim_bootstrap_limit_plugin(), mirroring sim_picker.c's
# own bootstrap-function role exactly) -- covering only a subset of them
# would repeat core.c's own siblings' (core_events.c/core_session.c/
# core_clock.c) never-mechanically-covered gap for the sim driver, which is
# exactly the omission a prior round of this same task left in place by
# adding sim_limit.c to scheduler_srcs above without also adding it here.
# Same "compiling to an object is enough, no real linking needed" rationale
# as sched_core_isolation_lib above.
sched_sim_isolation_lib = static_library(
'sched_sim_isolation',
['src/sim.c', 'src/sim_loop.c', 'src/sim_picker.c', 'src/sim_record.c',
'src/repl.c', 'src/repl_fmt.c', 'src/repl_break.c', 'src/repl_info.c',
'src/repl_params.c', 'src/repl_rollup.c'],
['src/sim.c', 'src/sim_loop.c', 'src/sim_picker.c', 'src/sim_limit.c',
'src/sim_record.c', 'src/repl.c', 'src/repl_fmt.c', 'src/repl_break.c',
'src/repl_info.c', 'src/repl_params.c', 'src/repl_rollup.c'],
include_directories: incdir,
dependencies: scheduler_deps,
install: false)

View file

@ -46,24 +46,34 @@ static int limit_priv_data_init(limit_plugin_data_t* data)
return 0;
}
static int limit_update_config(xce_sched_plugin_t* plugin,
xce_conf4sched_t* config)
/*
* limit_seed_config_impl - shared seed-loop body behind both
* limit_update_config() (normal-mode config_hook, below) and
* limit_seed_config() (bug-1825 remediation round 2, near
* limit_new_plugin() below): builds and registers one xce_limit_t per
* config->limits[] entry against `core`'s real group managers.
* Parameterized on an honestly-typed xce_sched_core_t* -- neither caller
* derives `core` from a plugin->sched cast inside this function; each
* caller resolves its own `core` argument in whatever way is safe for its
* own context (see each caller's doc comment).
*/
static int limit_seed_config_impl(xce_sched_plugin_t* plugin,
xce_sched_core_t* core,
xce_conf4sched_t* config)
{
limit_plugin_data_t* privdata = NULL;
xce_scheduler_t* sched = (xce_scheduler_t*)plugin->sched;
int i;
xce_limit_config_t** limits = config->limits;
int nlimits = config->nlimits;
TRACE("%s ...", __func__);
privdata = (limit_plugin_data_t*)plugin->data;
for (i = 0; i < nlimits; i++) {
int rc;
xce_limit_t* limit;
rc = build_limit(&limit, (sched->core.ugmgr), (sched->core.qgmgr),
(sched->core.pgmgr), (sched->core.hgmgr), limits[i]);
rc = build_limit(&limit, (core->ugmgr), (core->qgmgr),
(core->pgmgr), (core->hgmgr), limits[i]);
if (rc < 0) {
return rc;
}
@ -114,6 +124,16 @@ static int limit_update_config(xce_sched_plugin_t* plugin,
return 0;
}
static int limit_update_config(xce_sched_plugin_t* plugin,
xce_conf4sched_t* config)
{
xce_scheduler_t* sched = (xce_scheduler_t*)plugin->sched;
TRACE("%s ...", __func__);
return limit_seed_config_impl(plugin, &(sched->core), config);
}
typedef struct {
xce_sched_plugin_t* plugin;
xce_sched_ctx_t* ctx;
@ -606,9 +626,23 @@ var limit_get_usage_instances(xce_sched_core_t* core)
return privdata->instances;
}
int register_limit(void* sched)
/*
* limit_new_plugin - factory half of register_limit()'s template-build
* step, extracted so a caller with no xce_scheduler_t* (e.g. the
* simulation driver, via plugin_register_core() -- see sim_limit.c) can
* obtain a freshly calloc'd, fully populated `xce_sched_plugin_t` for the
* limit plugin -- same hooks/init_fn/fini_fn template register_limit()
* itself uses, just not yet registered anywhere. Mirrors
* builtin_fcfs_new_plugin()'s (plugins/builtin_fcfs.c) identical
* extraction exactly (scheduler-sim-diagnostics spec, task 6; bug-1825).
* Returns NULL on allocation failure. Caller owns the returned plugin
* (frees it only on a subsequent registration failure -- once registered,
* the plugin registry owns it, same lifetime rule every other plugin
* category in this codebase already follows).
*/
xce_sched_plugin_t* limit_new_plugin(void)
{
static xce_sched_plugin_t limit_plugin = {
static xce_sched_plugin_t limit_plugin_template = {
.name = "xce_sched_limit",
.hooks
= { .job_election_hook = (plugin_job_election_hook_t)limit_job_election,
@ -622,11 +656,63 @@ int register_limit(void* sched)
xce_sched_plugin_t* plugin
= (xce_sched_plugin_t*)calloc(1, sizeof(*plugin));
if (plugin == NULL) {
return NULL;
}
memcpy(plugin, &limit_plugin_template, sizeof(*plugin));
return plugin;
}
/*
* limit_seed_config - bug-1825 remediation round 2: honestly-typed
* config-seed entry point for a caller that holds a real xce_sched_core_t*
* but NOT a real xce_scheduler_t* -- the simulation driver
* (sim_limit.c's sim_bootstrap_limit_plugin()), whose
* xce_sched_sim_driver_t (sim.h) embeds a bare xce_sched_core_t core as
* its FIRST field, not a full xce_scheduler_t.
*
* This exists instead of routing the simulation driver through
* limit_update_config()/plugin->hooks.config_hook via a
* `plugin->sched = (void*)sim` type-pun (the round-1 approach, since
* removed) because that pun reproduces a cross-cast bug this codebase has
* already made once, for real: core.h's own xce_core_cache_clear_cb_t doc
* comment documents alloc_cache.c's cache_clear(xce_scheduler_t*) once
* being invoked unconditionally against BOTH drivers via this identical
* pointer-to-first-member idiom, and in sim mode silently reinterpreting
* xce_sched_sim_driver_t's `alt_events_file` (a live FILE*) as
* `unsatisfiable_cache` (a kvtab_t*) -- corrupting it. That bug's own fix
* was a structurally-typed per-core hook defaulting to NULL in sim mode,
* not a narrower comment scoping a still-present cast. This function
* applies the same discipline: `core` is a REAL field both
* xce_scheduler_t and xce_sched_sim_driver_t genuinely have (no cast
* needed to obtain it), so nothing this function or limit_seed_config_impl()
* reads can ever reach past xce_sched_core_t's own bounds into whatever
* xce_sched_sim_driver_t field happens to follow `core` in memory --
* unlike a plugin->sched cast, which compiles and "works" regardless of
* the target's true layout until a future edit reads one field too many.
*
* plugin->sched is never read or written by this function. Delegates to
* the same limit_seed_config_impl() helper limit_update_config() itself
* uses, so the two entry points can never silently diverge in behavior.
*/
int limit_seed_config(xce_sched_plugin_t* plugin, xce_sched_core_t* core,
xce_conf4sched_t* config)
{
TRACE("%s ...", __func__);
return limit_seed_config_impl(plugin, core, config);
}
int register_limit(void* sched)
{
xce_sched_plugin_t* plugin = limit_new_plugin();
if (plugin == NULL) {
return -ENOMEM;
}
memcpy(plugin, &limit_plugin, sizeof(*plugin));
return plugin_register(sched, plugin);
}

View file

@ -0,0 +1,143 @@
#include <stdlib.h>
#include "plugin.h"
#include "sim.h"
#include "utils.h"
/*
* sim_limit.c - simulation driver limit-plugin bootstrap
* (scheduler-sim-diagnostics spec, task 6; bug-1825 fix). Split out of
* sim_loop.c rather than folded into it, for the exact same reason its
* sibling sim_picker.c already is a separate file: sim_loop.c's own file
* header comment states it has "zero line-budget headroom" (this
* project's 800-line-per-file convention, src/scheduler/CLAUDE.md's
* "Files stay under the repo's 800-line cap") -- so new bootstrap logic
* goes in its own sibling file rather than growing sim_loop.c past its
* cap, the same "new sibling file when the owning file hits its cap"
* precedent this family has already established repeatedly (sim_loop.c
* itself, sim_record.c, repl.c, repl_break.c/repl_info.c, repl_params.c,
* and sim_picker.c).
*
* bug-1825: the limit plugin's normal-mode registration entry point,
* register_limit() (plugins/limit.c), has exactly one call site in the
* whole codebase -- normal-mode-only sched_register_plugins()
* (scheduler.c). The simulation driver's own plugin bootstrap
* (sim_bootstrap_picker(), sim_picker.c) only ever registers the picker
* plugin, so the limit plugin is never registered in sim mode at all --
* the REPL's `info limit` command (repl_info.c) is fully correct but
* permanently inert against a real replay, since
* limit_get_configured_limits() (plugins/limit.c) finds no
* "xce_sched_limit" entry in core->plugins to return anything from.
*
* sim_locate_and_load_snapshot() (sim.c) already loads the ORIGINAL live
* session's full config into sim->core.config (a borrowed reference --
* xce_sched_core_load_snapshot()'s own documented choice, referenced in
* sim.c's comment right after that call) before this function's caller
* (sim_loop.c) ever runs -- so whatever limit configuration
* (config->limits/config->nlimits) the original session had is already
* sitting there, just never handed to a limit plugin because none is ever
* registered. sim_bootstrap_limit_plugin() below fixes both halves:
* register the plugin against the simulation core (mirroring
* sim_bootstrap_picker()'s own plugin_register_core() call exactly), then
* -- only if a config is actually present -- seed it directly via the
* plugin's own config_hook, deliberately bypassing plugin_config_update()
* (plugin.c): that function casts its void* arg to xce_scheduler_t* and
* reads sched->core.plugins, which would misinterpret
* xce_sched_sim_driver_t's memory layout (it embeds a bare
* xce_sched_core_t core as its FIRST field, not a full xce_scheduler_t) --
* calling it here would be a type-unsafe read of whatever field happens
* to immediately follow `core` in xce_sched_sim_driver_t (sim.h).
*
* Explicit non-goal (tracked as its own, separate, larger follow-up bug):
* this does NOT wire limit *matching* (limit_job_election(),
* plugins/limit.c) into the sim/replay decision path -- only the
* configured-setting display becomes real here. Live usage display still
* correctly shows "no active usage instance yet" against a real replay
* even after this fix, since no job is ever matched against the limit in
* sim mode.
*
* plugin->sched wrinkle, and why this does NOT type-pun around it (bug-1825
* remediation round 2 -- found via a real ASAN SEGV while TDD-ing the
* original fix, then rejected on independent review): limit_update_config()
* -- the limit plugin's config_hook, unlike builtin_fcfs's picker hooks --
* internally casts plugin->sched to xce_scheduler_t* and dereferences
* sched->core.ugmgr/qgmgr/pgmgr/hgmgr (plugins/limit.c) to resolve each
* configured limit's consumer groups (build_limit()). plugin_register_core()
* deliberately leaves plugin->sched NULL (plugin.h's own doc comment on
* that function), because the picker category it was built for
* (sim_bootstrap_picker(), sim_picker.c) never dereferences plugin->sched
* in any hook -- the limit plugin's config_hook does, so calling it here
* via plugin->hooks.config_hook with plugin->sched still NULL segfaults on
* sched->core.ugmgr.
*
* The round-1 fix pointed plugin->sched at `sim` itself before invoking the
* hook, via the "pointer-to-first-member idiom" (xce_scheduler_t's own
* first field is also `xce_sched_core_t core`, at the same offset
* xce_sched_sim_driver_t's `core` sits at). Independent review rejected
* this: it is the EXACT SAME cross-cast idiom that already caused a real,
* documented production bug in this codebase -- core.h's own
* xce_core_cache_clear_cb_t doc comment describes alloc_cache.c's
* cache_clear(xce_scheduler_t*) once being called unconditionally from
* both drivers via this identical pointer-to-first-member trick, and in
* sim mode silently reinterpreting xce_sched_sim_driver_t's
* `alt_events_file` (a live FILE*) as `unsatisfiable_cache` (a kvtab_t*),
* corrupting it. That bug's own accepted fix was a structural,
* per-core-instance function-pointer hook defaulting to NULL in sim mode
* (xce_core_set_cache_clear_cb()) -- not "confine the cast by manual
* code-reading and a comment," because nothing stops a future edit to
* limit_update_config() from reading plugin->sched past ->core (e.g.
* ->apictx) and silently corrupting memory beyond the real
* xce_sched_sim_driver_t allocation, exactly as the cache_clear() bug did.
*
* Fix here follows that same precedent instead of repeating the type-pun:
* plugins/limit.c exposes limit_seed_config(xce_sched_plugin_t*,
* xce_sched_core_t* core, xce_conf4sched_t*) -- an honestly-typed entry
* point parameterized directly on `core`, the REAL field both
* xce_scheduler_t and xce_sched_sim_driver_t genuinely have (no cast
* needed), sharing its seed logic with limit_update_config() via a common
* static helper so the two paths cannot silently diverge. Called below
* with &(sim->core) -- plugin->sched is never written or read anywhere in
* this file.
*/
/* Consumed by sim_loop.c via a plain `extern` declared there -- same
* "extern declared where consumed" idiom this file family already uses
* throughout (sim_picker.c's own file header comment). */
void sim_bootstrap_limit_plugin(xce_sched_sim_driver_t* sim)
{
xce_sched_plugin_t* plugin;
plugin = limit_new_plugin();
if (plugin == NULL) {
ERROR("%s out of memory building the limit plugin instance", __func__);
return;
}
if (plugin_register_core(&(sim->core), plugin) < 0) {
ERROR("%s failed to register the limit plugin against the "
"simulation core",
__func__);
free(plugin);
return;
}
/* bug-1825: seed the freshly registered plugin with whatever limit
* configuration the replay's snapshot already carries in
* sim->core.config (set earlier by sched_sim_driver_start()'s
* snapshot load) -- via limit_seed_config() (plugins/limit.c), NOT
* plugin_config_update() (see this file's header comment for why that
* function is unsafe to call here) and NOT plugin->hooks.config_hook
* via a plugin->sched type-pun (see this file's header comment,
* "plugin->sched wrinkle", for why that round-1 approach was rejected
* on review and replaced with this honestly-typed call). Skipped
* silently when no config is present: the normal case for a replay
* whose snapshot carries no config, or for a test fixture that
* doesn't set one up -- not an error. */
if (sim->core.config != NULL) {
/* &(sim->core) is a REAL xce_sched_core_t* -- no cast, and
* plugin->sched is never touched. See limit_seed_config()'s own
* doc comment (plugins/limit.c) for why this is safe where the
* type-punned alternative was not. */
limit_seed_config(plugin, &(sim->core), sim->core.config);
}
}

View file

@ -407,6 +407,16 @@ static int sim_process_replay_event_message(xce_sched_sim_driver_t* sim,
* trace. */
extern void sim_bootstrap_picker(xce_sched_sim_driver_t* sim);
/* sim_bootstrap_limit_plugin - scheduler-sim-diagnostics spec, task 6
* (bug-1825 fix): registers the limit plugin against the simulation core
* and seeds it from sim->core.config, if present, so `info limit` shows
* real data against a replay. Moved to sim_limit.c (this file's own "zero
* line-budget headroom", see this file's header comment) -- extern'd here
* per this file family's established "declared where consumed" idiom,
* same as sim_bootstrap_picker() immediately above. See sim_limit.c's own
* file header comment for the full mechanism/bug trace. */
extern void sim_bootstrap_limit_plugin(xce_sched_sim_driver_t* sim);
/*
* sim_print_decision - Req 5 AC 19's default: "If --sim-output is not
* specified, decisions are printed to stdout only." This task (11.2) owns
@ -940,6 +950,7 @@ int sched_sim_driver_run(xce_sched_sim_driver_t* sim,
xce_repl_pre_replay_pause(sim);
sim_bootstrap_picker(sim);
sim_bootstrap_limit_plugin(sim);
/* Req 5 AC 19 (task 11.5): the first two --sim-output messages, written
* exactly once, before the event loop below runs -- see sim_record.c's

View file

@ -148,6 +148,7 @@
#include "../src/sim.c"
#include "../src/sim_loop.c"
#include "../src/sim_picker.c"
#include "../src/sim_limit.c" /* bug-1825: sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin() (sim_loop.c-cap sibling, sim_picker.c's own bug-1567 precedent) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_record.c"
#include "../src/sim_verify.c"
#include "../src/snapshot.c"
@ -193,6 +194,41 @@ var limit_get_usage_instances(xce_sched_core_t* core)
return NULL;
}
/* scheduler-sim-diagnostics spec, task 6 (bug-1825): sim_loop.c's
* sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin()
* (sim_limit.c, pulled into this TU via the #include above), which in
* turn calls limit_new_plugin() (plugins/limit.c, not part of this TU) --
* identical link-satisfying stub rationale as limit_get_configured_
* limits()/limit_get_usage_instances() immediately above. Returning NULL
* here is also the behaviorally correct answer, not just a link
* placeholder: sim_bootstrap_limit_plugin() already handles a NULL
* limit_new_plugin() return gracefully (logs an ERROR, registers nothing,
* returns) -- the exact same "out of memory" path sim_bootstrap_picker()
* (sim_picker.c) takes for a NULL builtin_fcfs_new_plugin() -- so this
* file's fixtures simply end up with no limit plugin registered, same
* observable state as before this task. */
xce_sched_plugin_t* limit_new_plugin(void)
{
return NULL;
}
/* limit_seed_config() (plugins/limit.c, not part of this TU) -- bug-1825
* remediation round 2's new honestly-typed config-seed entry point.
* sim_bootstrap_limit_plugin() (sim_limit.c) only calls it after
* plugin_register_core() has already succeeded against a real, non-NULL
* limit_new_plugin() plugin -- unreachable in this file since the
* limit_new_plugin() stub immediately above always returns NULL, but the
* symbol must still resolve at link time. Same link-satisfying-stub
* rationale as limit_new_plugin() immediately above. */
int limit_seed_config(xce_sched_plugin_t* plugin, xce_sched_core_t* core,
xce_conf4sched_t* config)
{
(void)plugin;
(void)core;
(void)config;
return 0;
}
int sched_reconcile_job_resource_usage(xce_sched_core_t* c,
xce_job_account_t* a,
xce_job_rusages_t* r)

View file

@ -88,6 +88,7 @@
#include "../src/sim.c"
#include "../src/sim_loop.c"
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() now calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_limit.c" /* bug-1825: sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin() (sim_loop.c-cap sibling, sim_picker.c's own bug-1567 precedent) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_record.c"
#include "../src/sim_verify.c"
#include "../src/snapshot.c"
@ -129,6 +130,41 @@ var limit_get_usage_instances(xce_sched_core_t* core)
return NULL;
}
/* scheduler-sim-diagnostics spec, task 6 (bug-1825): sim_loop.c's
* sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin()
* (sim_limit.c, pulled into this TU via the #include above), which in
* turn calls limit_new_plugin() (plugins/limit.c, not part of this TU) --
* identical link-satisfying stub rationale as limit_get_configured_
* limits()/limit_get_usage_instances() immediately above. Returning NULL
* here is also the behaviorally correct answer, not just a link
* placeholder: sim_bootstrap_limit_plugin() already handles a NULL
* limit_new_plugin() return gracefully (logs an ERROR, registers nothing,
* returns) -- the exact same "out of memory" path sim_bootstrap_picker()
* (sim_picker.c) takes for a NULL builtin_fcfs_new_plugin() -- so this
* file's fixtures simply end up with no limit plugin registered, same
* observable state as before this task. */
xce_sched_plugin_t* limit_new_plugin(void)
{
return NULL;
}
/* limit_seed_config() (plugins/limit.c, not part of this TU) -- bug-1825
* remediation round 2's new honestly-typed config-seed entry point.
* sim_bootstrap_limit_plugin() (sim_limit.c) only calls it after
* plugin_register_core() has already succeeded against a real, non-NULL
* limit_new_plugin() plugin -- unreachable in this file since the
* limit_new_plugin() stub immediately above always returns NULL, but the
* symbol must still resolve at link time. Same link-satisfying-stub
* rationale as limit_new_plugin() immediately above. */
int limit_seed_config(xce_sched_plugin_t* plugin, xce_sched_core_t* core,
xce_conf4sched_t* config)
{
(void)plugin;
(void)core;
(void)config;
return 0;
}
/* resource-accounting.md's reconciliation (resource.c, not linked here --
* this file only #includes core_events.c). core_events.c's
* XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts !=

View file

@ -137,6 +137,7 @@
#include "../src/sim.c"
#include "../src/sim_loop.c"
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() now calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_limit.c" /* bug-1825: sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin() (sim_loop.c-cap sibling, sim_picker.c's own bug-1567 precedent) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_record.c"
#include "../src/sim_verify.c"
#include "../src/snapshot.c"
@ -178,6 +179,41 @@ var limit_get_usage_instances(xce_sched_core_t* core)
return NULL;
}
/* scheduler-sim-diagnostics spec, task 6 (bug-1825): sim_loop.c's
* sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin()
* (sim_limit.c, pulled into this TU via the #include above), which in
* turn calls limit_new_plugin() (plugins/limit.c, not part of this TU) --
* identical link-satisfying stub rationale as limit_get_configured_
* limits()/limit_get_usage_instances() immediately above. Returning NULL
* here is also the behaviorally correct answer, not just a link
* placeholder: sim_bootstrap_limit_plugin() already handles a NULL
* limit_new_plugin() return gracefully (logs an ERROR, registers nothing,
* returns) -- the exact same "out of memory" path sim_bootstrap_picker()
* (sim_picker.c) takes for a NULL builtin_fcfs_new_plugin() -- so this
* file's fixtures simply end up with no limit plugin registered, same
* observable state as before this task. */
xce_sched_plugin_t* limit_new_plugin(void)
{
return NULL;
}
/* limit_seed_config() (plugins/limit.c, not part of this TU) -- bug-1825
* remediation round 2's new honestly-typed config-seed entry point.
* sim_bootstrap_limit_plugin() (sim_limit.c) only calls it after
* plugin_register_core() has already succeeded against a real, non-NULL
* limit_new_plugin() plugin -- unreachable in this file since the
* limit_new_plugin() stub immediately above always returns NULL, but the
* symbol must still resolve at link time. Same link-satisfying-stub
* rationale as limit_new_plugin() immediately above. */
int limit_seed_config(xce_sched_plugin_t* plugin, xce_sched_core_t* core,
xce_conf4sched_t* config)
{
(void)plugin;
(void)core;
(void)config;
return 0;
}
/* resource-accounting.md's reconciliation (resource.c, not linked here --
* this file only #includes core_events.c). core_events.c's
* XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts !=

View file

@ -105,6 +105,7 @@
#include "../src/sim.c"
#include "../src/sim_loop.c"
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() now calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_limit.c" /* bug-1825: sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin() (sim_loop.c-cap sibling, sim_picker.c's own bug-1567 precedent) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_record.c"
#include "../src/sim_verify.c"
#include "../src/snapshot.c"
@ -146,6 +147,41 @@ var limit_get_usage_instances(xce_sched_core_t* core)
return NULL;
}
/* scheduler-sim-diagnostics spec, task 6 (bug-1825): sim_loop.c's
* sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin()
* (sim_limit.c, pulled into this TU via the #include above), which in
* turn calls limit_new_plugin() (plugins/limit.c, not part of this TU) --
* identical link-satisfying stub rationale as limit_get_configured_
* limits()/limit_get_usage_instances() immediately above. Returning NULL
* here is also the behaviorally correct answer, not just a link
* placeholder: sim_bootstrap_limit_plugin() already handles a NULL
* limit_new_plugin() return gracefully (logs an ERROR, registers nothing,
* returns) -- the exact same "out of memory" path sim_bootstrap_picker()
* (sim_picker.c) takes for a NULL builtin_fcfs_new_plugin() -- so this
* file's fixtures simply end up with no limit plugin registered, same
* observable state as before this task. */
xce_sched_plugin_t* limit_new_plugin(void)
{
return NULL;
}
/* limit_seed_config() (plugins/limit.c, not part of this TU) -- bug-1825
* remediation round 2's new honestly-typed config-seed entry point.
* sim_bootstrap_limit_plugin() (sim_limit.c) only calls it after
* plugin_register_core() has already succeeded against a real, non-NULL
* limit_new_plugin() plugin -- unreachable in this file since the
* limit_new_plugin() stub immediately above always returns NULL, but the
* symbol must still resolve at link time. Same link-satisfying-stub
* rationale as limit_new_plugin() immediately above. */
int limit_seed_config(xce_sched_plugin_t* plugin, xce_sched_core_t* core,
xce_conf4sched_t* config)
{
(void)plugin;
(void)core;
(void)config;
return 0;
}
/* resource-accounting.md's reconciliation (resource.c, not linked here --
* this file only #includes core_events.c). core_events.c's
* XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts !=

View file

@ -102,6 +102,7 @@
#include "../src/sim.c"
#include "../src/sim_loop.c"
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() now calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_limit.c" /* bug-1825: sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin() (sim_loop.c-cap sibling, sim_picker.c's own bug-1567 precedent) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_record.c"
#include "../src/sim_verify.c"
#include "../src/snapshot.c"
@ -143,6 +144,41 @@ var limit_get_usage_instances(xce_sched_core_t* core)
return NULL;
}
/* scheduler-sim-diagnostics spec, task 6 (bug-1825): sim_loop.c's
* sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin()
* (sim_limit.c, pulled into this TU via the #include above), which in
* turn calls limit_new_plugin() (plugins/limit.c, not part of this TU) --
* identical link-satisfying stub rationale as limit_get_configured_
* limits()/limit_get_usage_instances() immediately above. Returning NULL
* here is also the behaviorally correct answer, not just a link
* placeholder: sim_bootstrap_limit_plugin() already handles a NULL
* limit_new_plugin() return gracefully (logs an ERROR, registers nothing,
* returns) -- the exact same "out of memory" path sim_bootstrap_picker()
* (sim_picker.c) takes for a NULL builtin_fcfs_new_plugin() -- so this
* file's fixtures simply end up with no limit plugin registered, same
* observable state as before this task. */
xce_sched_plugin_t* limit_new_plugin(void)
{
return NULL;
}
/* limit_seed_config() (plugins/limit.c, not part of this TU) -- bug-1825
* remediation round 2's new honestly-typed config-seed entry point.
* sim_bootstrap_limit_plugin() (sim_limit.c) only calls it after
* plugin_register_core() has already succeeded against a real, non-NULL
* limit_new_plugin() plugin -- unreachable in this file since the
* limit_new_plugin() stub immediately above always returns NULL, but the
* symbol must still resolve at link time. Same link-satisfying-stub
* rationale as limit_new_plugin() immediately above. */
int limit_seed_config(xce_sched_plugin_t* plugin, xce_sched_core_t* core,
xce_conf4sched_t* config)
{
(void)plugin;
(void)core;
(void)config;
return 0;
}
/* resource-accounting.md's reconciliation (resource.c, not linked here --
* this file only #includes core_events.c). core_events.c's
* XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts !=

View file

@ -97,6 +97,7 @@
#include "../src/sim.c"
#include "../src/sim_loop.c"
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() now calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_limit.c" /* bug-1825: sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin() (sim_loop.c-cap sibling, sim_picker.c's own bug-1567 precedent) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_record.c"
#include "../src/sim_verify.c"
#include "../src/snapshot.c"
@ -138,6 +139,41 @@ var limit_get_usage_instances(xce_sched_core_t* core)
return NULL;
}
/* scheduler-sim-diagnostics spec, task 6 (bug-1825): sim_loop.c's
* sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin()
* (sim_limit.c, pulled into this TU via the #include above), which in
* turn calls limit_new_plugin() (plugins/limit.c, not part of this TU) --
* identical link-satisfying stub rationale as limit_get_configured_
* limits()/limit_get_usage_instances() immediately above. Returning NULL
* here is also the behaviorally correct answer, not just a link
* placeholder: sim_bootstrap_limit_plugin() already handles a NULL
* limit_new_plugin() return gracefully (logs an ERROR, registers nothing,
* returns) -- the exact same "out of memory" path sim_bootstrap_picker()
* (sim_picker.c) takes for a NULL builtin_fcfs_new_plugin() -- so this
* file's fixtures simply end up with no limit plugin registered, same
* observable state as before this task. */
xce_sched_plugin_t* limit_new_plugin(void)
{
return NULL;
}
/* limit_seed_config() (plugins/limit.c, not part of this TU) -- bug-1825
* remediation round 2's new honestly-typed config-seed entry point.
* sim_bootstrap_limit_plugin() (sim_limit.c) only calls it after
* plugin_register_core() has already succeeded against a real, non-NULL
* limit_new_plugin() plugin -- unreachable in this file since the
* limit_new_plugin() stub immediately above always returns NULL, but the
* symbol must still resolve at link time. Same link-satisfying-stub
* rationale as limit_new_plugin() immediately above. */
int limit_seed_config(xce_sched_plugin_t* plugin, xce_sched_core_t* core,
xce_conf4sched_t* config)
{
(void)plugin;
(void)core;
(void)config;
return 0;
}
/* resource-accounting.md's reconciliation (resource.c, not linked here --
* this file only #includes core_events.c). core_events.c's
* XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts !=

View file

@ -90,6 +90,7 @@
#include "../src/sim.c"
#include "../src/sim_loop.c"
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() now calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_limit.c" /* bug-1825: sched_sim_driver_run() now calls sim_bootstrap_limit_plugin() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_record.c"
#include "../src/sim_verify.c"
#include "../src/snapshot.c"
@ -2395,6 +2396,180 @@ test_repl_step_continue_with_info_limit_interleaved_matches_baseline_decision_se
"baseline_decision_sequence: PASS\n");
}
/* ---------------------------------------------------------------------- */
/* scheduler-sim-diagnostics spec, task 6 (bug-1825 fix): sim mode never */
/* registers the limit plugin at all, so `info limit`'s otherwise-correct */
/* display logic (tested above via the hand-rolled register_limit_plugin() */
/* fixture) is permanently inert against a REAL replay. These tests drive */
/* the actual production bootstrap function, sim_bootstrap_limit_plugin() */
/* (new src/sim_limit.c, sim_loop.c's sim_bootstrap_picker()-call-site */
/* sibling), against a real xce_sched_core_init()-initialized core -- not */
/* the register_limit_plugin()/fixture_register_plugin_in_core() shortcut */
/* the rest of this file's tests use, since the whole point here is */
/* proving the real bootstrap path (registration + config-seed) works, */
/* not re-proving repl_info_limit()'s own display logic again. */
/* ---------------------------------------------------------------------- */
/*
* (1) Registration: before sim_bootstrap_limit_plugin() runs, the limit
* plugin is not present in sim->core.plugins at all (limit_get_configured_
* limits()'s own documented "plugin absent" NULL return). After it runs,
* the accessor resolves a real, iterable handle -- proving the function
* actually registered "xce_sched_limit" against the simulation core via
* plugin_register_core(), mirroring sim_bootstrap_picker()'s own
* registration call exactly.
*/
static void
test_sim_bootstrap_limit_plugin_registers_plugin_against_real_core(void)
{
xce_sched_sim_driver_t sim;
var limits_handle;
int rc;
memset(&sim, 0, sizeof(sim));
rc = xce_sched_core_init(&(sim.core));
TEST_ASSERT_EQUAL_INT(0, rc);
limits_handle = limit_get_configured_limits(&(sim.core));
TEST_ASSERT_NULL_MESSAGE(
limits_handle,
"the limit plugin must not be registered before "
"sim_bootstrap_limit_plugin() runs");
sim_bootstrap_limit_plugin(&sim);
limits_handle = limit_get_configured_limits(&(sim.core));
TEST_ASSERT_NOT_NULL_MESSAGE(
limits_handle,
"sim_bootstrap_limit_plugin() must register the limit plugin "
"against sim->core, matching sim_bootstrap_picker()'s own "
"plugin_register_core() pattern");
printf(
"test_sim_bootstrap_limit_plugin_registers_plugin_against_real_"
"core: PASS\n");
}
/*
* (2) THE observable criterion (task 6's own stated Observable): a real
* xce_sched_sim_driver_t whose core.config already carries a real
* xce_limit_config_t (as sim_locate_and_load_snapshot()/
* xce_sched_core_load_snapshot() would have set it up from a replay's own
* snapshot, before sim_bootstrap_limit_plugin() ever runs -- reproduced
* here via direct construction per this task's own stated test-level
* guidance, no capnp/.replay file needed) ends up with
* limit_get_configured_limits() iterating to that SAME real limit by name
* once sim_bootstrap_limit_plugin() runs. This is the test that actually
* proves the config-seed step (limit_seed_config(), plugins/limit.c,
* called directly with a real xce_sched_core_t* -- bug-1825 remediation
* round 2 replaced the original plugin->sched-type-punned
* plugin->hooks.config_hook() call with this honestly-typed entry point;
* see sim_limit.c's own header comment for why), not just registration.
*/
static void
test_sim_bootstrap_limit_plugin_seeds_real_config_limit_when_config_present(
void)
{
xce_sched_sim_driver_t sim;
xce_limit_config_t* limits[1];
xce_conf4sched_t config;
var limits_handle;
iterator_t it;
xce_limit_t* found = NULL;
int rc;
memset(&sim, 0, sizeof(sim));
rc = xce_sched_core_init(&(sim.core));
TEST_ASSERT_EQUAL_INT(0, rc);
limits[0] = make_limit_config("sim_replay_limit");
memset(&config, 0, sizeof(config));
config.nlimits = 1;
config.limits = limits;
/* Mirrors sim_locate_and_load_snapshot()'s (sim.c) borrowed-reference
* assignment of sim->core.config from the replay's own snapshot --
* this test only needs the END STATE that call produces, not the
* capnp/file machinery that gets there. */
sim.core.config = &config;
sim_bootstrap_limit_plugin(&sim);
limits_handle = limit_get_configured_limits(&(sim.core));
TEST_ASSERT_NOT_NULL(limits_handle);
rc = iter_make(&it, limits_handle);
TEST_ASSERT_TRUE(rc >= 0);
rc = iter_next(&it, (void**)&found);
TEST_ASSERT_TRUE(rc >= 0);
TEST_ASSERT_NOT_EQUAL(RTTI_ITER_NO_DATA, rc);
TEST_ASSERT_NOT_NULL(found);
TEST_ASSERT_EQUAL_STRING_MESSAGE(
"sim_replay_limit", found->name,
"sim_bootstrap_limit_plugin() must seed the plugin with the REAL "
"limit already sitting in sim->core.config, not merely register "
"an empty plugin");
rc = iter_next(&it, (void**)&found);
TEST_ASSERT_EQUAL_INT(RTTI_ITER_NO_DATA, rc);
iter_destroy(&it);
free_limit_config(limits[0]);
printf(
"test_sim_bootstrap_limit_plugin_seeds_real_config_limit_when_"
"config_present: PASS\n");
}
/*
* (3) Graceful no-config case (task 6's explicit design constraint): a
* replay whose snapshot carries no config -- or a test fixture that never
* sets one up -- leaves sim->core.config NULL. sim_bootstrap_limit_plugin()
* must still register the plugin successfully (non-NULL, empty-iterating
* accessor handle) and must NOT crash attempting to seed a config that
* does not exist; this is the normal case, not an error.
*/
static void
test_sim_bootstrap_limit_plugin_registers_without_crash_when_config_null(
void)
{
xce_sched_sim_driver_t sim;
var limits_handle;
iterator_t it;
void* item = NULL;
int rc;
memset(&sim, 0, sizeof(sim));
rc = xce_sched_core_init(&(sim.core));
TEST_ASSERT_EQUAL_INT(0, rc);
TEST_ASSERT_NULL(sim.core.config);
sim_bootstrap_limit_plugin(&sim);
limits_handle = limit_get_configured_limits(&(sim.core));
TEST_ASSERT_NOT_NULL_MESSAGE(
limits_handle,
"the plugin must still register successfully when "
"sim->core.config is NULL -- the config-seed step must be "
"skipped silently, not treated as a registration failure");
rc = iter_make(&it, limits_handle);
TEST_ASSERT_TRUE(rc >= 0);
rc = iter_next(&it, &item);
TEST_ASSERT_EQUAL_INT(RTTI_ITER_NO_DATA, rc);
iter_destroy(&it);
printf(
"test_sim_bootstrap_limit_plugin_registers_without_crash_when_"
"config_null: PASS\n");
}
int main(void)
{
UNITY_BEGIN();
@ -2443,5 +2618,11 @@ int main(void)
test_info_limit_on_empty_registry_is_repeatable_and_never_registers_plugin);
RUN_TEST(
test_repl_step_continue_with_info_limit_interleaved_matches_baseline_decision_sequence);
RUN_TEST(
test_sim_bootstrap_limit_plugin_registers_plugin_against_real_core);
RUN_TEST(
test_sim_bootstrap_limit_plugin_seeds_real_config_limit_when_config_present);
RUN_TEST(
test_sim_bootstrap_limit_plugin_registers_without_crash_when_config_null);
return UNITY_END();
}

View file

@ -101,6 +101,7 @@
#include "../src/sim.c"
#include "../src/sim_loop.c"
#include "../src/sim_picker.c"
#include "../src/sim_limit.c" /* bug-1825: sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin() (sim_loop.c-cap sibling, sim_picker.c's own bug-1567 precedent) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_record.c"
#include "../src/sim_verify.c"
#include "../src/snapshot.c"
@ -142,6 +143,41 @@ var limit_get_usage_instances(xce_sched_core_t* core)
return NULL;
}
/* scheduler-sim-diagnostics spec, task 6 (bug-1825): sim_loop.c's
* sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin()
* (sim_limit.c, pulled into this TU via the #include above), which in
* turn calls limit_new_plugin() (plugins/limit.c, not part of this TU) --
* identical link-satisfying stub rationale as limit_get_configured_
* limits()/limit_get_usage_instances() immediately above. Returning NULL
* here is also the behaviorally correct answer, not just a link
* placeholder: sim_bootstrap_limit_plugin() already handles a NULL
* limit_new_plugin() return gracefully (logs an ERROR, registers nothing,
* returns) -- the exact same "out of memory" path sim_bootstrap_picker()
* (sim_picker.c) takes for a NULL builtin_fcfs_new_plugin() -- so this
* file's fixtures simply end up with no limit plugin registered, same
* observable state as before this task. */
xce_sched_plugin_t* limit_new_plugin(void)
{
return NULL;
}
/* limit_seed_config() (plugins/limit.c, not part of this TU) -- bug-1825
* remediation round 2's new honestly-typed config-seed entry point.
* sim_bootstrap_limit_plugin() (sim_limit.c) only calls it after
* plugin_register_core() has already succeeded against a real, non-NULL
* limit_new_plugin() plugin -- unreachable in this file since the
* limit_new_plugin() stub immediately above always returns NULL, but the
* symbol must still resolve at link time. Same link-satisfying-stub
* rationale as limit_new_plugin() immediately above. */
int limit_seed_config(xce_sched_plugin_t* plugin, xce_sched_core_t* core,
xce_conf4sched_t* config)
{
(void)plugin;
(void)core;
(void)config;
return 0;
}
/* Link-satisfying stubs -- same rationale as every sibling in this file
* family (see test_repl_execution_control.c's own copies for the full
* per-stub doc comments). */

View file

@ -68,6 +68,7 @@
#include "../src/sim.c"
#include "../src/sim_loop.c"
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() now calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_limit.c" /* bug-1825: sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin() (sim_loop.c-cap sibling, sim_picker.c's own bug-1567 precedent) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_record.c"
#include "../src/sim_verify.c"
#include "../src/snapshot.c"
@ -109,6 +110,41 @@ var limit_get_usage_instances(xce_sched_core_t* core)
return NULL;
}
/* scheduler-sim-diagnostics spec, task 6 (bug-1825): sim_loop.c's
* sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin()
* (sim_limit.c, pulled into this TU via the #include above), which in
* turn calls limit_new_plugin() (plugins/limit.c, not part of this TU) --
* identical link-satisfying stub rationale as limit_get_configured_
* limits()/limit_get_usage_instances() immediately above. Returning NULL
* here is also the behaviorally correct answer, not just a link
* placeholder: sim_bootstrap_limit_plugin() already handles a NULL
* limit_new_plugin() return gracefully (logs an ERROR, registers nothing,
* returns) -- the exact same "out of memory" path sim_bootstrap_picker()
* (sim_picker.c) takes for a NULL builtin_fcfs_new_plugin() -- so this
* file's fixtures simply end up with no limit plugin registered, same
* observable state as before this task. */
xce_sched_plugin_t* limit_new_plugin(void)
{
return NULL;
}
/* limit_seed_config() (plugins/limit.c, not part of this TU) -- bug-1825
* remediation round 2's new honestly-typed config-seed entry point.
* sim_bootstrap_limit_plugin() (sim_limit.c) only calls it after
* plugin_register_core() has already succeeded against a real, non-NULL
* limit_new_plugin() plugin -- unreachable in this file since the
* limit_new_plugin() stub immediately above always returns NULL, but the
* symbol must still resolve at link time. Same link-satisfying-stub
* rationale as limit_new_plugin() immediately above. */
int limit_seed_config(xce_sched_plugin_t* plugin, xce_sched_core_t* core,
xce_conf4sched_t* config)
{
(void)plugin;
(void)core;
(void)config;
return 0;
}
/* resource-accounting.md's reconciliation (resource.c, not linked here --
* this file only #includes core_events.c). core_events.c's
* XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts !=

View file

@ -64,6 +64,7 @@
#include "../src/sim.c"
#include "../src/sim_loop.c"
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() now calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_limit.c" /* bug-1825: sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin() (sim_loop.c-cap sibling, sim_picker.c's own bug-1567 precedent) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_record.c"
#include "../src/sim_verify.c"
#include "../src/snapshot.c"
@ -105,6 +106,41 @@ var limit_get_usage_instances(xce_sched_core_t* core)
return NULL;
}
/* scheduler-sim-diagnostics spec, task 6 (bug-1825): sim_loop.c's
* sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin()
* (sim_limit.c, pulled into this TU via the #include above), which in
* turn calls limit_new_plugin() (plugins/limit.c, not part of this TU) --
* identical link-satisfying stub rationale as limit_get_configured_
* limits()/limit_get_usage_instances() immediately above. Returning NULL
* here is also the behaviorally correct answer, not just a link
* placeholder: sim_bootstrap_limit_plugin() already handles a NULL
* limit_new_plugin() return gracefully (logs an ERROR, registers nothing,
* returns) -- the exact same "out of memory" path sim_bootstrap_picker()
* (sim_picker.c) takes for a NULL builtin_fcfs_new_plugin() -- so this
* file's fixtures simply end up with no limit plugin registered, same
* observable state as before this task. */
xce_sched_plugin_t* limit_new_plugin(void)
{
return NULL;
}
/* limit_seed_config() (plugins/limit.c, not part of this TU) -- bug-1825
* remediation round 2's new honestly-typed config-seed entry point.
* sim_bootstrap_limit_plugin() (sim_limit.c) only calls it after
* plugin_register_core() has already succeeded against a real, non-NULL
* limit_new_plugin() plugin -- unreachable in this file since the
* limit_new_plugin() stub immediately above always returns NULL, but the
* symbol must still resolve at link time. Same link-satisfying-stub
* rationale as limit_new_plugin() immediately above. */
int limit_seed_config(xce_sched_plugin_t* plugin, xce_sched_core_t* core,
xce_conf4sched_t* config)
{
(void)plugin;
(void)core;
(void)config;
return 0;
}
/* resource-accounting.md's reconciliation (resource.c, not linked here --
* this file only #includes core_events.c). core_events.c's
* XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts !=

View file

@ -77,6 +77,7 @@
#include "../src/sim.c"
#include "../src/sim_loop.c"
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() now calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_limit.c" /* bug-1825: sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin() (sim_loop.c-cap sibling, sim_picker.c's own bug-1567 precedent) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_record.c"
#include "../src/sim_verify.c"
#include "../src/snapshot.c"
@ -118,6 +119,41 @@ var limit_get_usage_instances(xce_sched_core_t* core)
return NULL;
}
/* scheduler-sim-diagnostics spec, task 6 (bug-1825): sim_loop.c's
* sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin()
* (sim_limit.c, pulled into this TU via the #include above), which in
* turn calls limit_new_plugin() (plugins/limit.c, not part of this TU) --
* identical link-satisfying stub rationale as limit_get_configured_
* limits()/limit_get_usage_instances() immediately above. Returning NULL
* here is also the behaviorally correct answer, not just a link
* placeholder: sim_bootstrap_limit_plugin() already handles a NULL
* limit_new_plugin() return gracefully (logs an ERROR, registers nothing,
* returns) -- the exact same "out of memory" path sim_bootstrap_picker()
* (sim_picker.c) takes for a NULL builtin_fcfs_new_plugin() -- so this
* file's fixtures simply end up with no limit plugin registered, same
* observable state as before this task. */
xce_sched_plugin_t* limit_new_plugin(void)
{
return NULL;
}
/* limit_seed_config() (plugins/limit.c, not part of this TU) -- bug-1825
* remediation round 2's new honestly-typed config-seed entry point.
* sim_bootstrap_limit_plugin() (sim_limit.c) only calls it after
* plugin_register_core() has already succeeded against a real, non-NULL
* limit_new_plugin() plugin -- unreachable in this file since the
* limit_new_plugin() stub immediately above always returns NULL, but the
* symbol must still resolve at link time. Same link-satisfying-stub
* rationale as limit_new_plugin() immediately above. */
int limit_seed_config(xce_sched_plugin_t* plugin, xce_sched_core_t* core,
xce_conf4sched_t* config)
{
(void)plugin;
(void)core;
(void)config;
return 0;
}
/* resource-accounting.md's reconciliation (resource.c, not linked here --
* this file only #includes core_events.c). core_events.c's
* XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts !=

View file

@ -118,6 +118,7 @@
#include "../src/sim.c"
#include "../src/sim_loop.c"
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() now calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_limit.c" /* bug-1825: sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin() (sim_loop.c-cap sibling, sim_picker.c's own bug-1567 precedent) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_record.c"
#include "../src/sim_verify.c"
#include "../src/snapshot.c"
@ -159,6 +160,41 @@ var limit_get_usage_instances(xce_sched_core_t* core)
return NULL;
}
/* scheduler-sim-diagnostics spec, task 6 (bug-1825): sim_loop.c's
* sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin()
* (sim_limit.c, pulled into this TU via the #include above), which in
* turn calls limit_new_plugin() (plugins/limit.c, not part of this TU) --
* identical link-satisfying stub rationale as limit_get_configured_
* limits()/limit_get_usage_instances() immediately above. Returning NULL
* here is also the behaviorally correct answer, not just a link
* placeholder: sim_bootstrap_limit_plugin() already handles a NULL
* limit_new_plugin() return gracefully (logs an ERROR, registers nothing,
* returns) -- the exact same "out of memory" path sim_bootstrap_picker()
* (sim_picker.c) takes for a NULL builtin_fcfs_new_plugin() -- so this
* file's fixtures simply end up with no limit plugin registered, same
* observable state as before this task. */
xce_sched_plugin_t* limit_new_plugin(void)
{
return NULL;
}
/* limit_seed_config() (plugins/limit.c, not part of this TU) -- bug-1825
* remediation round 2's new honestly-typed config-seed entry point.
* sim_bootstrap_limit_plugin() (sim_limit.c) only calls it after
* plugin_register_core() has already succeeded against a real, non-NULL
* limit_new_plugin() plugin -- unreachable in this file since the
* limit_new_plugin() stub immediately above always returns NULL, but the
* symbol must still resolve at link time. Same link-satisfying-stub
* rationale as limit_new_plugin() immediately above. */
int limit_seed_config(xce_sched_plugin_t* plugin, xce_sched_core_t* core,
xce_conf4sched_t* config)
{
(void)plugin;
(void)core;
(void)config;
return 0;
}
/* resource-accounting.md's reconciliation (resource.c, not linked here --
* this file only #includes core_events.c). core_events.c's
* XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts !=

View file

@ -95,6 +95,7 @@
#include "../src/sim.c"
#include "../src/sim_loop.c"
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() now calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_limit.c" /* bug-1825: sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin() (sim_loop.c-cap sibling, sim_picker.c's own bug-1567 precedent) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_record.c"
#include "../src/sim_verify.c"
#include "../src/snapshot.c"
@ -136,6 +137,41 @@ var limit_get_usage_instances(xce_sched_core_t* core)
return NULL;
}
/* scheduler-sim-diagnostics spec, task 6 (bug-1825): sim_loop.c's
* sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin()
* (sim_limit.c, pulled into this TU via the #include above), which in
* turn calls limit_new_plugin() (plugins/limit.c, not part of this TU) --
* identical link-satisfying stub rationale as limit_get_configured_
* limits()/limit_get_usage_instances() immediately above. Returning NULL
* here is also the behaviorally correct answer, not just a link
* placeholder: sim_bootstrap_limit_plugin() already handles a NULL
* limit_new_plugin() return gracefully (logs an ERROR, registers nothing,
* returns) -- the exact same "out of memory" path sim_bootstrap_picker()
* (sim_picker.c) takes for a NULL builtin_fcfs_new_plugin() -- so this
* file's fixtures simply end up with no limit plugin registered, same
* observable state as before this task. */
xce_sched_plugin_t* limit_new_plugin(void)
{
return NULL;
}
/* limit_seed_config() (plugins/limit.c, not part of this TU) -- bug-1825
* remediation round 2's new honestly-typed config-seed entry point.
* sim_bootstrap_limit_plugin() (sim_limit.c) only calls it after
* plugin_register_core() has already succeeded against a real, non-NULL
* limit_new_plugin() plugin -- unreachable in this file since the
* limit_new_plugin() stub immediately above always returns NULL, but the
* symbol must still resolve at link time. Same link-satisfying-stub
* rationale as limit_new_plugin() immediately above. */
int limit_seed_config(xce_sched_plugin_t* plugin, xce_sched_core_t* core,
xce_conf4sched_t* config)
{
(void)plugin;
(void)core;
(void)config;
return 0;
}
void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; }
/* resource-accounting.md's reconciliation (resource.c, not linked here --

View file

@ -180,6 +180,7 @@
#include "../src/sim.c"
#include "../src/sim_loop.c"
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_limit.c" /* bug-1825: sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin() (sim_loop.c-cap sibling, sim_picker.c's own bug-1567 precedent) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_record.c"
#include "../src/sim_verify.c"
#include "../src/snapshot.c"
@ -221,6 +222,41 @@ var limit_get_usage_instances(xce_sched_core_t* core)
return NULL;
}
/* scheduler-sim-diagnostics spec, task 6 (bug-1825): sim_loop.c's
* sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin()
* (sim_limit.c, pulled into this TU via the #include above), which in
* turn calls limit_new_plugin() (plugins/limit.c, not part of this TU) --
* identical link-satisfying stub rationale as limit_get_configured_
* limits()/limit_get_usage_instances() immediately above. Returning NULL
* here is also the behaviorally correct answer, not just a link
* placeholder: sim_bootstrap_limit_plugin() already handles a NULL
* limit_new_plugin() return gracefully (logs an ERROR, registers nothing,
* returns) -- the exact same "out of memory" path sim_bootstrap_picker()
* (sim_picker.c) takes for a NULL builtin_fcfs_new_plugin() -- so this
* file's fixtures simply end up with no limit plugin registered, same
* observable state as before this task. */
xce_sched_plugin_t* limit_new_plugin(void)
{
return NULL;
}
/* limit_seed_config() (plugins/limit.c, not part of this TU) -- bug-1825
* remediation round 2's new honestly-typed config-seed entry point.
* sim_bootstrap_limit_plugin() (sim_limit.c) only calls it after
* plugin_register_core() has already succeeded against a real, non-NULL
* limit_new_plugin() plugin -- unreachable in this file since the
* limit_new_plugin() stub immediately above always returns NULL, but the
* symbol must still resolve at link time. Same link-satisfying-stub
* rationale as limit_new_plugin() immediately above. */
int limit_seed_config(xce_sched_plugin_t* plugin, xce_sched_core_t* core,
xce_conf4sched_t* config)
{
(void)plugin;
(void)core;
(void)config;
return 0;
}
/* xce_sched_driver_on_decision()'s (driver.c) publish-side linker
* dependencies -- never actually invoked: this file never registers a
* decision callback. Same rationale test_sim_resource_contention.c's own

View file

@ -203,6 +203,7 @@
#include "../src/sim.c"
#include "../src/sim_loop.c"
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_limit.c" /* bug-1825: sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin() (sim_loop.c-cap sibling, sim_picker.c's own bug-1567 precedent) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_record.c"
#include "../src/sim_verify.c"
#include "../src/snapshot.c"
@ -244,6 +245,41 @@ var limit_get_usage_instances(xce_sched_core_t* core)
return NULL;
}
/* scheduler-sim-diagnostics spec, task 6 (bug-1825): sim_loop.c's
* sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin()
* (sim_limit.c, pulled into this TU via the #include above), which in
* turn calls limit_new_plugin() (plugins/limit.c, not part of this TU) --
* identical link-satisfying stub rationale as limit_get_configured_
* limits()/limit_get_usage_instances() immediately above. Returning NULL
* here is also the behaviorally correct answer, not just a link
* placeholder: sim_bootstrap_limit_plugin() already handles a NULL
* limit_new_plugin() return gracefully (logs an ERROR, registers nothing,
* returns) -- the exact same "out of memory" path sim_bootstrap_picker()
* (sim_picker.c) takes for a NULL builtin_fcfs_new_plugin() -- so this
* file's fixtures simply end up with no limit plugin registered, same
* observable state as before this task. */
xce_sched_plugin_t* limit_new_plugin(void)
{
return NULL;
}
/* limit_seed_config() (plugins/limit.c, not part of this TU) -- bug-1825
* remediation round 2's new honestly-typed config-seed entry point.
* sim_bootstrap_limit_plugin() (sim_limit.c) only calls it after
* plugin_register_core() has already succeeded against a real, non-NULL
* limit_new_plugin() plugin -- unreachable in this file since the
* limit_new_plugin() stub immediately above always returns NULL, but the
* symbol must still resolve at link time. Same link-satisfying-stub
* rationale as limit_new_plugin() immediately above. */
int limit_seed_config(xce_sched_plugin_t* plugin, xce_sched_core_t* core,
xce_conf4sched_t* config)
{
(void)plugin;
(void)core;
(void)config;
return 0;
}
/* resource.c's sched_try_alloc_on_host_()'s own link-time dependency --
* never actually invoked (this file calls sched_check_host_satisfy()/
* sched_charge_account()/sched_commit_job_alloc() directly). Same stub

View file

@ -164,6 +164,7 @@
#include "../src/sim.c"
#include "../src/sim_loop.c"
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() now calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_limit.c" /* bug-1825: sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin() (sim_loop.c-cap sibling, sim_picker.c's own bug-1567 precedent) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_record.c"
#include "../src/sim_verify.c"
#include "../src/snapshot.c"
@ -205,6 +206,41 @@ var limit_get_usage_instances(xce_sched_core_t* core)
return NULL;
}
/* scheduler-sim-diagnostics spec, task 6 (bug-1825): sim_loop.c's
* sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin()
* (sim_limit.c, pulled into this TU via the #include above), which in
* turn calls limit_new_plugin() (plugins/limit.c, not part of this TU) --
* identical link-satisfying stub rationale as limit_get_configured_
* limits()/limit_get_usage_instances() immediately above. Returning NULL
* here is also the behaviorally correct answer, not just a link
* placeholder: sim_bootstrap_limit_plugin() already handles a NULL
* limit_new_plugin() return gracefully (logs an ERROR, registers nothing,
* returns) -- the exact same "out of memory" path sim_bootstrap_picker()
* (sim_picker.c) takes for a NULL builtin_fcfs_new_plugin() -- so this
* file's fixtures simply end up with no limit plugin registered, same
* observable state as before this task. */
xce_sched_plugin_t* limit_new_plugin(void)
{
return NULL;
}
/* limit_seed_config() (plugins/limit.c, not part of this TU) -- bug-1825
* remediation round 2's new honestly-typed config-seed entry point.
* sim_bootstrap_limit_plugin() (sim_limit.c) only calls it after
* plugin_register_core() has already succeeded against a real, non-NULL
* limit_new_plugin() plugin -- unreachable in this file since the
* limit_new_plugin() stub immediately above always returns NULL, but the
* symbol must still resolve at link time. Same link-satisfying-stub
* rationale as limit_new_plugin() immediately above. */
int limit_seed_config(xce_sched_plugin_t* plugin, xce_sched_core_t* core,
xce_conf4sched_t* config)
{
(void)plugin;
(void)core;
(void)config;
return 0;
}
/* resource-accounting.md's reconciliation (resource.c, not linked here --
* this file only #includes core_events.c). core_events.c's
* XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts !=

View file

@ -111,6 +111,7 @@
#include "../src/sim.c"
#include "../src/sim_loop.c"
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() now calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_limit.c" /* bug-1825: sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin() (sim_loop.c-cap sibling, sim_picker.c's own bug-1567 precedent) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_record.c"
#include "../src/sim_verify.c"
#include "../src/snapshot.c"
@ -152,6 +153,41 @@ var limit_get_usage_instances(xce_sched_core_t* core)
return NULL;
}
/* scheduler-sim-diagnostics spec, task 6 (bug-1825): sim_loop.c's
* sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin()
* (sim_limit.c, pulled into this TU via the #include above), which in
* turn calls limit_new_plugin() (plugins/limit.c, not part of this TU) --
* identical link-satisfying stub rationale as limit_get_configured_
* limits()/limit_get_usage_instances() immediately above. Returning NULL
* here is also the behaviorally correct answer, not just a link
* placeholder: sim_bootstrap_limit_plugin() already handles a NULL
* limit_new_plugin() return gracefully (logs an ERROR, registers nothing,
* returns) -- the exact same "out of memory" path sim_bootstrap_picker()
* (sim_picker.c) takes for a NULL builtin_fcfs_new_plugin() -- so this
* file's fixtures simply end up with no limit plugin registered, same
* observable state as before this task. */
xce_sched_plugin_t* limit_new_plugin(void)
{
return NULL;
}
/* limit_seed_config() (plugins/limit.c, not part of this TU) -- bug-1825
* remediation round 2's new honestly-typed config-seed entry point.
* sim_bootstrap_limit_plugin() (sim_limit.c) only calls it after
* plugin_register_core() has already succeeded against a real, non-NULL
* limit_new_plugin() plugin -- unreachable in this file since the
* limit_new_plugin() stub immediately above always returns NULL, but the
* symbol must still resolve at link time. Same link-satisfying-stub
* rationale as limit_new_plugin() immediately above. */
int limit_seed_config(xce_sched_plugin_t* plugin, xce_sched_core_t* core,
xce_conf4sched_t* config)
{
(void)plugin;
(void)core;
(void)config;
return 0;
}
/* resource-accounting.md's reconciliation (resource.c, not linked here --
* this file only #includes core_events.c). core_events.c's
* XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts !=

View file

@ -123,6 +123,7 @@
#include "../src/sim.c"
#include "../src/sim_loop.c"
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() now calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_limit.c" /* bug-1825: sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin() (sim_loop.c-cap sibling, sim_picker.c's own bug-1567 precedent) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_record.c"
#include "../src/sim_verify.c"
#include "../src/snapshot.c"
@ -164,6 +165,41 @@ var limit_get_usage_instances(xce_sched_core_t* core)
return NULL;
}
/* scheduler-sim-diagnostics spec, task 6 (bug-1825): sim_loop.c's
* sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin()
* (sim_limit.c, pulled into this TU via the #include above), which in
* turn calls limit_new_plugin() (plugins/limit.c, not part of this TU) --
* identical link-satisfying stub rationale as limit_get_configured_
* limits()/limit_get_usage_instances() immediately above. Returning NULL
* here is also the behaviorally correct answer, not just a link
* placeholder: sim_bootstrap_limit_plugin() already handles a NULL
* limit_new_plugin() return gracefully (logs an ERROR, registers nothing,
* returns) -- the exact same "out of memory" path sim_bootstrap_picker()
* (sim_picker.c) takes for a NULL builtin_fcfs_new_plugin() -- so this
* file's fixtures simply end up with no limit plugin registered, same
* observable state as before this task. */
xce_sched_plugin_t* limit_new_plugin(void)
{
return NULL;
}
/* limit_seed_config() (plugins/limit.c, not part of this TU) -- bug-1825
* remediation round 2's new honestly-typed config-seed entry point.
* sim_bootstrap_limit_plugin() (sim_limit.c) only calls it after
* plugin_register_core() has already succeeded against a real, non-NULL
* limit_new_plugin() plugin -- unreachable in this file since the
* limit_new_plugin() stub immediately above always returns NULL, but the
* symbol must still resolve at link time. Same link-satisfying-stub
* rationale as limit_new_plugin() immediately above. */
int limit_seed_config(xce_sched_plugin_t* plugin, xce_sched_core_t* core,
xce_conf4sched_t* config)
{
(void)plugin;
(void)core;
(void)config;
return 0;
}
/* resource-accounting.md's reconciliation (resource.c, not linked here --
* this file only #includes core_events.c). core_events.c's
* XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts !=

View file

@ -126,6 +126,7 @@
#include "../src/sim.c"
#include "../src/sim_loop.c"
#include "../src/sim_picker.c" /* bug-1567: sim_loop.c calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_limit.c" /* bug-1825: sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin() (sim_loop.c-cap sibling, sim_picker.c's own bug-1567 precedent) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_record.c"
#include "../src/sim_verify.c"
#include "../src/snapshot.c"
@ -167,6 +168,41 @@ var limit_get_usage_instances(xce_sched_core_t* core)
return NULL;
}
/* scheduler-sim-diagnostics spec, task 6 (bug-1825): sim_loop.c's
* sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin()
* (sim_limit.c, pulled into this TU via the #include above), which in
* turn calls limit_new_plugin() (plugins/limit.c, not part of this TU) --
* identical link-satisfying stub rationale as limit_get_configured_
* limits()/limit_get_usage_instances() immediately above. Returning NULL
* here is also the behaviorally correct answer, not just a link
* placeholder: sim_bootstrap_limit_plugin() already handles a NULL
* limit_new_plugin() return gracefully (logs an ERROR, registers nothing,
* returns) -- the exact same "out of memory" path sim_bootstrap_picker()
* (sim_picker.c) takes for a NULL builtin_fcfs_new_plugin() -- so this
* file's fixtures simply end up with no limit plugin registered, same
* observable state as before this task. */
xce_sched_plugin_t* limit_new_plugin(void)
{
return NULL;
}
/* limit_seed_config() (plugins/limit.c, not part of this TU) -- bug-1825
* remediation round 2's new honestly-typed config-seed entry point.
* sim_bootstrap_limit_plugin() (sim_limit.c) only calls it after
* plugin_register_core() has already succeeded against a real, non-NULL
* limit_new_plugin() plugin -- unreachable in this file since the
* limit_new_plugin() stub immediately above always returns NULL, but the
* symbol must still resolve at link time. Same link-satisfying-stub
* rationale as limit_new_plugin() immediately above. */
int limit_seed_config(xce_sched_plugin_t* plugin, xce_sched_core_t* core,
xce_conf4sched_t* config)
{
(void)plugin;
(void)core;
(void)config;
return 0;
}
/* sched_worker_release_host_ctx() is now a REAL (non-stub) symbol pulled in
* from resource.c (task 2.1 addition, below) -- no local stand-in needed or
* permitted (a local definition here would collide at link time). Unused by

View file

@ -82,6 +82,7 @@
#include "../src/sim.c"
#include "../src/sim_loop.c"
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() now calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_limit.c" /* bug-1825: sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin() (sim_loop.c-cap sibling, sim_picker.c's own bug-1567 precedent) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_record.c"
#include "../src/sim_verify.c"
#include "../src/snapshot.c"
@ -123,6 +124,41 @@ var limit_get_usage_instances(xce_sched_core_t* core)
return NULL;
}
/* scheduler-sim-diagnostics spec, task 6 (bug-1825): sim_loop.c's
* sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin()
* (sim_limit.c, pulled into this TU via the #include above), which in
* turn calls limit_new_plugin() (plugins/limit.c, not part of this TU) --
* identical link-satisfying stub rationale as limit_get_configured_
* limits()/limit_get_usage_instances() immediately above. Returning NULL
* here is also the behaviorally correct answer, not just a link
* placeholder: sim_bootstrap_limit_plugin() already handles a NULL
* limit_new_plugin() return gracefully (logs an ERROR, registers nothing,
* returns) -- the exact same "out of memory" path sim_bootstrap_picker()
* (sim_picker.c) takes for a NULL builtin_fcfs_new_plugin() -- so this
* file's fixtures simply end up with no limit plugin registered, same
* observable state as before this task. */
xce_sched_plugin_t* limit_new_plugin(void)
{
return NULL;
}
/* limit_seed_config() (plugins/limit.c, not part of this TU) -- bug-1825
* remediation round 2's new honestly-typed config-seed entry point.
* sim_bootstrap_limit_plugin() (sim_limit.c) only calls it after
* plugin_register_core() has already succeeded against a real, non-NULL
* limit_new_plugin() plugin -- unreachable in this file since the
* limit_new_plugin() stub immediately above always returns NULL, but the
* symbol must still resolve at link time. Same link-satisfying-stub
* rationale as limit_new_plugin() immediately above. */
int limit_seed_config(xce_sched_plugin_t* plugin, xce_sched_core_t* core,
xce_conf4sched_t* config)
{
(void)plugin;
(void)core;
(void)config;
return 0;
}
/* resource-accounting.md's reconciliation (resource.c, not linked here --
* this file only #includes core_events.c). core_events.c's
* XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts !=

View file

@ -147,6 +147,7 @@
#include "../src/sim.c"
#include "../src/sim_loop.c"
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() now calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_limit.c" /* bug-1825: sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin() (sim_loop.c-cap sibling, sim_picker.c's own bug-1567 precedent) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_record.c"
#include "../src/sim_verify.c"
#include "../src/snapshot.c"
@ -188,6 +189,41 @@ var limit_get_usage_instances(xce_sched_core_t* core)
return NULL;
}
/* scheduler-sim-diagnostics spec, task 6 (bug-1825): sim_loop.c's
* sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin()
* (sim_limit.c, pulled into this TU via the #include above), which in
* turn calls limit_new_plugin() (plugins/limit.c, not part of this TU) --
* identical link-satisfying stub rationale as limit_get_configured_
* limits()/limit_get_usage_instances() immediately above. Returning NULL
* here is also the behaviorally correct answer, not just a link
* placeholder: sim_bootstrap_limit_plugin() already handles a NULL
* limit_new_plugin() return gracefully (logs an ERROR, registers nothing,
* returns) -- the exact same "out of memory" path sim_bootstrap_picker()
* (sim_picker.c) takes for a NULL builtin_fcfs_new_plugin() -- so this
* file's fixtures simply end up with no limit plugin registered, same
* observable state as before this task. */
xce_sched_plugin_t* limit_new_plugin(void)
{
return NULL;
}
/* limit_seed_config() (plugins/limit.c, not part of this TU) -- bug-1825
* remediation round 2's new honestly-typed config-seed entry point.
* sim_bootstrap_limit_plugin() (sim_limit.c) only calls it after
* plugin_register_core() has already succeeded against a real, non-NULL
* limit_new_plugin() plugin -- unreachable in this file since the
* limit_new_plugin() stub immediately above always returns NULL, but the
* symbol must still resolve at link time. Same link-satisfying-stub
* rationale as limit_new_plugin() immediately above. */
int limit_seed_config(xce_sched_plugin_t* plugin, xce_sched_core_t* core,
xce_conf4sched_t* config)
{
(void)plugin;
(void)core;
(void)config;
return 0;
}
/* xce_sched_driver_run_normal_mode_round()'s (driver.c) linker dependency --
* a no-op stand-in, same rationale test_sim_equivalence.c's own copy
* documents (this file drives its own resource accounting directly via

View file

@ -115,6 +115,7 @@
#include "../src/sim.c"
#include "../src/sim_loop.c"
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_limit.c" /* bug-1825: sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin() (sim_loop.c-cap sibling, sim_picker.c's own bug-1567 precedent) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_record.c"
#include "../src/sim_verify.c"
#include "../src/snapshot.c"
@ -156,6 +157,41 @@ var limit_get_usage_instances(xce_sched_core_t* core)
return NULL;
}
/* scheduler-sim-diagnostics spec, task 6 (bug-1825): sim_loop.c's
* sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin()
* (sim_limit.c, pulled into this TU via the #include above), which in
* turn calls limit_new_plugin() (plugins/limit.c, not part of this TU) --
* identical link-satisfying stub rationale as limit_get_configured_
* limits()/limit_get_usage_instances() immediately above. Returning NULL
* here is also the behaviorally correct answer, not just a link
* placeholder: sim_bootstrap_limit_plugin() already handles a NULL
* limit_new_plugin() return gracefully (logs an ERROR, registers nothing,
* returns) -- the exact same "out of memory" path sim_bootstrap_picker()
* (sim_picker.c) takes for a NULL builtin_fcfs_new_plugin() -- so this
* file's fixtures simply end up with no limit plugin registered, same
* observable state as before this task. */
xce_sched_plugin_t* limit_new_plugin(void)
{
return NULL;
}
/* limit_seed_config() (plugins/limit.c, not part of this TU) -- bug-1825
* remediation round 2's new honestly-typed config-seed entry point.
* sim_bootstrap_limit_plugin() (sim_limit.c) only calls it after
* plugin_register_core() has already succeeded against a real, non-NULL
* limit_new_plugin() plugin -- unreachable in this file since the
* limit_new_plugin() stub immediately above always returns NULL, but the
* symbol must still resolve at link time. Same link-satisfying-stub
* rationale as limit_new_plugin() immediately above. */
int limit_seed_config(xce_sched_plugin_t* plugin, xce_sched_core_t* core,
xce_conf4sched_t* config)
{
(void)plugin;
(void)core;
(void)config;
return 0;
}
/* resource.c's sched_try_alloc_on_host_()'s own link-time dependency --
* never actually invoked (this file calls sched_check_host_satisfy()
* directly, never sched_try_alloc_on_hosts()/sched_try_alloc_on_host_()

View file

@ -147,6 +147,7 @@
#include "../src/sim.c"
#include "../src/sim_loop.c"
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_limit.c" /* bug-1825: sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin() (sim_loop.c-cap sibling, sim_picker.c's own bug-1567 precedent) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_record.c"
#include "../src/sim_verify.c"
#include "../src/snapshot.c"
@ -188,6 +189,41 @@ var limit_get_usage_instances(xce_sched_core_t* core)
return NULL;
}
/* scheduler-sim-diagnostics spec, task 6 (bug-1825): sim_loop.c's
* sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin()
* (sim_limit.c, pulled into this TU via the #include above), which in
* turn calls limit_new_plugin() (plugins/limit.c, not part of this TU) --
* identical link-satisfying stub rationale as limit_get_configured_
* limits()/limit_get_usage_instances() immediately above. Returning NULL
* here is also the behaviorally correct answer, not just a link
* placeholder: sim_bootstrap_limit_plugin() already handles a NULL
* limit_new_plugin() return gracefully (logs an ERROR, registers nothing,
* returns) -- the exact same "out of memory" path sim_bootstrap_picker()
* (sim_picker.c) takes for a NULL builtin_fcfs_new_plugin() -- so this
* file's fixtures simply end up with no limit plugin registered, same
* observable state as before this task. */
xce_sched_plugin_t* limit_new_plugin(void)
{
return NULL;
}
/* limit_seed_config() (plugins/limit.c, not part of this TU) -- bug-1825
* remediation round 2's new honestly-typed config-seed entry point.
* sim_bootstrap_limit_plugin() (sim_limit.c) only calls it after
* plugin_register_core() has already succeeded against a real, non-NULL
* limit_new_plugin() plugin -- unreachable in this file since the
* limit_new_plugin() stub immediately above always returns NULL, but the
* symbol must still resolve at link time. Same link-satisfying-stub
* rationale as limit_new_plugin() immediately above. */
int limit_seed_config(xce_sched_plugin_t* plugin, xce_sched_core_t* core,
xce_conf4sched_t* config)
{
(void)plugin;
(void)core;
(void)config;
return 0;
}
/* core_reset_workers()'s (core_session.c) linker dependency -- never
* invoked (no worker is ever added here). */
void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; }

View file

@ -101,6 +101,7 @@
#include "../src/sim.c"
#include "../src/sim_loop.c"
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_limit.c" /* bug-1825: sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin() (sim_loop.c-cap sibling, sim_picker.c's own bug-1567 precedent) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_record.c"
#include "../src/sim_verify.c"
#include "../src/snapshot.c"
@ -142,6 +143,41 @@ var limit_get_usage_instances(xce_sched_core_t* core)
return NULL;
}
/* scheduler-sim-diagnostics spec, task 6 (bug-1825): sim_loop.c's
* sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin()
* (sim_limit.c, pulled into this TU via the #include above), which in
* turn calls limit_new_plugin() (plugins/limit.c, not part of this TU) --
* identical link-satisfying stub rationale as limit_get_configured_
* limits()/limit_get_usage_instances() immediately above. Returning NULL
* here is also the behaviorally correct answer, not just a link
* placeholder: sim_bootstrap_limit_plugin() already handles a NULL
* limit_new_plugin() return gracefully (logs an ERROR, registers nothing,
* returns) -- the exact same "out of memory" path sim_bootstrap_picker()
* (sim_picker.c) takes for a NULL builtin_fcfs_new_plugin() -- so this
* file's fixtures simply end up with no limit plugin registered, same
* observable state as before this task. */
xce_sched_plugin_t* limit_new_plugin(void)
{
return NULL;
}
/* limit_seed_config() (plugins/limit.c, not part of this TU) -- bug-1825
* remediation round 2's new honestly-typed config-seed entry point.
* sim_bootstrap_limit_plugin() (sim_limit.c) only calls it after
* plugin_register_core() has already succeeded against a real, non-NULL
* limit_new_plugin() plugin -- unreachable in this file since the
* limit_new_plugin() stub immediately above always returns NULL, but the
* symbol must still resolve at link time. Same link-satisfying-stub
* rationale as limit_new_plugin() immediately above. */
int limit_seed_config(xce_sched_plugin_t* plugin, xce_sched_core_t* core,
xce_conf4sched_t* config)
{
(void)plugin;
(void)core;
(void)config;
return 0;
}
/* core_reset_workers()'s (core_session.c) linker dependency -- same stub
* test_sim_verify.c already establishes; never invoked (no worker is ever
* added here). */

View file

@ -102,6 +102,7 @@
#include "../src/sim.c"
#include "../src/sim_loop.c"
#include "../src/sim_picker.c" /* bug-1567: sched_sim_driver_run() now calls sim_bootstrap_picker() (sim_loop.c-cap sibling) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_limit.c" /* bug-1825: sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin() (sim_loop.c-cap sibling, sim_picker.c's own bug-1567 precedent) as an extern -- undefined reference at link time otherwise */
#include "../src/sim_record.c"
#include "../src/sim_verify.c"
#include "../src/snapshot.c"
@ -143,6 +144,41 @@ var limit_get_usage_instances(xce_sched_core_t* core)
return NULL;
}
/* scheduler-sim-diagnostics spec, task 6 (bug-1825): sim_loop.c's
* sched_sim_driver_run() now also calls sim_bootstrap_limit_plugin()
* (sim_limit.c, pulled into this TU via the #include above), which in
* turn calls limit_new_plugin() (plugins/limit.c, not part of this TU) --
* identical link-satisfying stub rationale as limit_get_configured_
* limits()/limit_get_usage_instances() immediately above. Returning NULL
* here is also the behaviorally correct answer, not just a link
* placeholder: sim_bootstrap_limit_plugin() already handles a NULL
* limit_new_plugin() return gracefully (logs an ERROR, registers nothing,
* returns) -- the exact same "out of memory" path sim_bootstrap_picker()
* (sim_picker.c) takes for a NULL builtin_fcfs_new_plugin() -- so this
* file's fixtures simply end up with no limit plugin registered, same
* observable state as before this task. */
xce_sched_plugin_t* limit_new_plugin(void)
{
return NULL;
}
/* limit_seed_config() (plugins/limit.c, not part of this TU) -- bug-1825
* remediation round 2's new honestly-typed config-seed entry point.
* sim_bootstrap_limit_plugin() (sim_limit.c) only calls it after
* plugin_register_core() has already succeeded against a real, non-NULL
* limit_new_plugin() plugin -- unreachable in this file since the
* limit_new_plugin() stub immediately above always returns NULL, but the
* symbol must still resolve at link time. Same link-satisfying-stub
* rationale as limit_new_plugin() immediately above. */
int limit_seed_config(xce_sched_plugin_t* plugin, xce_sched_core_t* core,
xce_conf4sched_t* config)
{
(void)plugin;
(void)core;
(void)config;
return 0;
}
/* resource-accounting.md's reconciliation (resource.c, not linked here --
* this file only #includes core_events.c). core_events.c's
* XCE_CORE_EVENT_JOB_RUSAGE handler calls this whenever job->accounts !=