Files
chimera-gfx-Public/tools/phase10at_fd_deadline_model.py
T
Chimera GFX release export a6037502d7
phase0-ci / build-and-audit (push) Successful in 2m14s
Publish Chimera GFX source
2026-09-03 03:27:14 +02:00

206 lines
7.2 KiB
Python

#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Host-only RFFDG descriptor ownership and absolute deadline model."""
from __future__ import annotations
from dataclasses import dataclass
from phase10aq_worker_result_record import (
RECORD_SIZE, WorkerPrecommit, WorkerRecordError, parse_record,
)
MAX_TICKS = 256
MAX_READ_EVENTS = 256
CREATE_PIPE = "CREATE_PIPE"
SET_PARENT_READ_NONBLOCK = "SET_PARENT_READ_NONBLOCK"
SPAWN_RFFDG = "SPAWN_RFFDG"
PARENT_CLOSE_WRITE = "PARENT_CLOSE_WRITE"
CHILD_CLOSE_READ = "CHILD_CLOSE_READ"
CHILD_CLOSE_WRITE = "CHILD_CLOSE_WRITE"
PARENT_CLOSE_READ = "PARENT_CLOSE_READ"
TERMINATE_CHILD = "TERMINATE_CHILD"
REAP_CHILD = "REAP_CHILD"
OK = "OK"
ERROR = "ERROR"
DATA = "DATA"
EINTR = "EINTR"
WOULD_BLOCK = "WOULD_BLOCK"
EOF = "EOF"
OPERATIONS = {
CREATE_PIPE, SET_PARENT_READ_NONBLOCK, SPAWN_RFFDG,
PARENT_CLOSE_WRITE, CHILD_CLOSE_READ, CHILD_CLOSE_WRITE,
PARENT_CLOSE_READ, TERMINATE_CHILD, REAP_CHILD,
}
READ_KINDS = {DATA, EINTR, WOULD_BLOCK, EOF}
class FdModelError(RuntimeError):
"""The synthetic descriptor transaction cannot close safely."""
@dataclass(frozen=True)
class FakeFdEvent:
operation: str
result: str
ticks: int = 1
def __post_init__(self) -> None:
if self.operation not in OPERATIONS or self.result not in {OK, ERROR}:
raise FdModelError("FD event is invalid")
if not isinstance(self.ticks, int) or isinstance(self.ticks, bool) \
or not 1 <= self.ticks <= MAX_TICKS:
raise FdModelError("FD event ticks are invalid")
@dataclass(frozen=True)
class FakeRead:
kind: str
data: bytes = b""
ticks: int = 1
def __post_init__(self) -> None:
if self.kind not in READ_KINDS or type(self.data) is not bytes:
raise FdModelError("read event is invalid")
if (self.kind == DATA) != bool(self.data) or len(self.data) > RECORD_SIZE:
raise FdModelError("read payload is invalid")
if not isinstance(self.ticks, int) or isinstance(self.ticks, bool) \
or not 1 <= self.ticks <= MAX_TICKS:
raise FdModelError("read ticks are invalid")
class FakeFdFacade:
"""Exact scripted FD facade with no OS, process, clock or I/O imports."""
def __init__(self, events: tuple[FakeFdEvent, ...]) -> None:
if not isinstance(events, tuple) or not events \
or any(type(item) is not FakeFdEvent for item in events):
raise FdModelError("FD script is invalid")
self._events = list(events)
self.ticks = 0
def invoke(self, operation: str, cleanup: bool = False) -> str:
if not self._events:
raise FdModelError("FD script is exhausted")
event = self._events.pop(0)
if event.operation != operation:
raise FdModelError("FD operation ordering differs")
if not cleanup and self.ticks + event.ticks > MAX_TICKS:
raise FdModelError("absolute deadline precedes FD operation")
self.ticks += event.ticks
return event.result
@property
def remaining(self) -> int:
return len(self._events)
@dataclass(frozen=True)
class FdOutcome:
classification: str
success: bool
buffered: int
eintr_count: int
parent_fds_open: int
child_fds_open: int
worker_alive: bool
containment_required: bool
rffdg_used: bool = True
live_fd_present: bool = False
def _close(facade: FakeFdFacade, operation: str) -> None:
if facade.invoke(operation, cleanup=True) != OK:
raise FdModelError(f"terminal cleanup failed: {operation}")
def run_fd_transaction(precommit: WorkerPrecommit, facade: FakeFdFacade,
reads: tuple[FakeRead, ...]) -> FdOutcome:
"""Model exact descriptor ownership and one absolute deadline."""
if type(precommit) is not WorkerPrecommit or type(facade) is not FakeFdFacade \
or not isinstance(reads, tuple) or not 1 <= len(reads) <= MAX_READ_EVENTS \
or any(type(item) is not FakeRead for item in reads):
raise FdModelError("FD model boundary is invalid")
parent_read = parent_write = child_read = child_write = worker = False
failed = False
buffer = bytearray()
eintr_count = 0
try:
if facade.invoke(CREATE_PIPE) != OK:
failed = True
else:
parent_read = parent_write = True
if facade.invoke(SET_PARENT_READ_NONBLOCK) != OK:
failed = True
elif facade.invoke(SPAWN_RFFDG) != OK:
failed = True
else:
worker = child_read = child_write = True
if facade.invoke(PARENT_CLOSE_WRITE) != OK:
failed = True
else:
parent_write = False
if facade.invoke(CHILD_CLOSE_READ) != OK:
failed = True
else:
child_read = False
for index, read in enumerate(reads):
if facade.ticks + read.ticks > MAX_TICKS:
failed = True
break
facade.ticks += read.ticks
if read.kind == EINTR:
eintr_count += 1
continue
if read.kind == WOULD_BLOCK:
continue
if read.kind == EOF:
failed = True
break
if len(buffer) + len(read.data) > RECORD_SIZE:
failed = True
break
buffer.extend(read.data)
if len(buffer) == RECORD_SIZE:
if index != len(reads) - 1:
failed = True
break
try:
parse_record(bytes(buffer), precommit)
except WorkerRecordError:
failed = True
break
if len(buffer) != RECORD_SIZE:
failed = True
except FdModelError:
failed = True
if worker:
if failed:
_close(facade, TERMINATE_CHILD)
if child_read:
_close(facade, CHILD_CLOSE_READ)
child_read = False
if child_write:
_close(facade, CHILD_CLOSE_WRITE)
child_write = False
_close(facade, REAP_CHILD)
worker = False
if parent_write:
_close(facade, PARENT_CLOSE_WRITE)
parent_write = False
if parent_read:
_close(facade, PARENT_CLOSE_READ)
parent_read = False
if facade.remaining:
raise FdModelError("FD script has unused operations")
if failed:
return FdOutcome("OFFLINE_FD_TRANSACTION_CONTAINED", False,
len(buffer), eintr_count, 0, 0, False, True)
return FdOutcome("OFFLINE_FD_TRANSACTION_COMPLETE", True,
RECORD_SIZE, eintr_count, 0, 0, False, False)