mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-04 17:13:46 -06:00
feat: take the host probe lock per run
core_probe takes probe.lock itself around one execution, load check included, and releases it when the run ends. A campaign pass never holds it between runs, so two passes interleave. RETROBIOS_PROBE_LOCK names another file, RETROBIOS_PROBE_LOCK_HELD says the caller holds it. Tests use their own lock file.
This commit is contained in:
1 parent
b6ed5ba0a1
commit
fabd431adb
6 files changed
+129
-3
No files matched your search
@@ -1126,6 +1126,52 @@ class FakeCorePasses(Workspace):
|
||||
self.assertEqual({rep["verdict_evidence"]["rule"] for r in records for v in r["variants"]
|
||||
for rep in v["repetitions"]}, {"timeout"})
|
||||
|
||||
def test_two_passes_interleave_their_runs(self) -> None:
|
||||
"""Each core_probe takes the host lock for its own run: a pass never
|
||||
holds it between runs, so a second pass runs between them."""
|
||||
import threading
|
||||
import time
|
||||
|
||||
spans: dict[str, list[tuple[float, float]]] = {"a": [], "b": []}
|
||||
other = Workspace(methodName="setUp")
|
||||
other.setUp()
|
||||
self.addCleanup(other.tearDown)
|
||||
passes = []
|
||||
for name, workspace in (("a", self), ("b", other)):
|
||||
c = FakeCorePasses.passing(workspace, "hle") if workspace is self else self.passing_in(workspace)
|
||||
real = c.host.run
|
||||
|
||||
def timed(argv: list[str], *args: object, _name: str = name, _real=real, **kwargs: object):
|
||||
start = time.monotonic()
|
||||
try:
|
||||
return _real(argv, *args, **kwargs)
|
||||
finally:
|
||||
spans[_name].append((start, time.monotonic()))
|
||||
c.host.run = timed
|
||||
passes.append(c)
|
||||
threads = [threading.Thread(target=c.run, args=(set(), None)) for c in passes]
|
||||
for thread in threads:
|
||||
thread.start()
|
||||
for thread in threads:
|
||||
thread.join()
|
||||
ends = {name: sorted(end for _, end in runs) for name, runs in spans.items()}
|
||||
self.assertGreater(len(ends["a"]), 2)
|
||||
self.assertGreater(len(ends["b"]), 2)
|
||||
# Neither pass finished all its runs before the other started finishing its own.
|
||||
self.assertLess(ends["b"][0], ends["a"][-1])
|
||||
self.assertLess(ends["a"][0], ends["b"][-1])
|
||||
|
||||
def passing_in(self, workspace: Workspace) -> campaign.Campaign:
|
||||
workspace.put_game()
|
||||
host = campaign.Host(loadavg=lambda: (0.0, 0.0, 0.0), free_gb=lambda path: 500.0,
|
||||
cpu_count=1_000_000)
|
||||
c = campaign.Campaign(workspace.paths, campaign.Settings(
|
||||
check_repeat=2, probe_timeout=30, delays=(1,), echo=False), host,
|
||||
lock_path=workspace.tmp / "auto.lock")
|
||||
so = self.cores["hle"]
|
||||
c.unit_cores = lambda *a, **k: [campaign.Core("fake", so, campaign.file_sha256(so))]
|
||||
return c
|
||||
|
||||
def test_missing_content_leaves_the_checks_pending(self) -> None:
|
||||
c = self.passing(romfetch=str(self.tmp / "no-romfetch"))
|
||||
shutil.rmtree(self.game)
|
||||
|
||||
Reference in new issue
Block a user