From e0910ebd85092e587844892806abbdf70a6ef41d Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Tue, 6 Oct 2026 14:15:29 -0400 Subject: [PATCH] [Fix] (P13 W5 S7): the verify read hook answers the monolith verb port's neutral-pack window from the applied pack, as for a server-stamped verb. --- MobileGL/MG_Impl/Pipe/PipeFill.cpp | 8 +++++++- MobileGL/MG_Impl/Pipe/Verb/VerbPort.cpp | 15 +++++++++++++++ MobileGL/MG_Impl/Pipe/Verb/VerbPort.h | 8 ++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/MobileGL/MG_Impl/Pipe/PipeFill.cpp b/MobileGL/MG_Impl/Pipe/PipeFill.cpp index 78ff0e9a..bf9e6293 100644 --- a/MobileGL/MG_Impl/Pipe/PipeFill.cpp +++ b/MobileGL/MG_Impl/Pipe/PipeFill.cpp @@ -40,6 +40,9 @@ #include #include #include +#if MOBILEGL_BUILD_RECORD_ARM && MOBILEGL_PIPE_VERIFY +#include +#endif #if MOBILEGL_BUILD_DISAGGREGATED // R-8 (c1): the client's liveness gates read the caps mirror, never MGPipeGetResourceOps(). @@ -689,7 +692,10 @@ namespace MobileGL::MG_Pipe { const auto index = static_cast(field); if (kMGPipeInputFieldSticky[index]) return; #if MOBILEGL_BUILD_RECORD_ARM - if (self.ServerStampedVerb() && field == MGPipeInputField::GetPixelStoreParameters) { + // P13 W5: the monolith verb port applies records without a server stamp, and its readback + // forces the neutral pack around the backend's read exactly as the server's does. + if ((self.ServerStampedVerb() || MG_Record::MonolithPortApplyingForVerify()) && + field == MGPipeInputField::GetPixelStoreParameters) { // Compare the backend's pack field against the last payload applied to this // context, including the neutral-pack override during readback. Never obtain // the reference by reading the field being checked, or consult the client's diff --git a/MobileGL/MG_Impl/Pipe/Verb/VerbPort.cpp b/MobileGL/MG_Impl/Pipe/Verb/VerbPort.cpp index fe925910..5ccd0506 100644 --- a/MobileGL/MG_Impl/Pipe/Verb/VerbPort.cpp +++ b/MobileGL/MG_Impl/Pipe/Verb/VerbPort.cpp @@ -230,8 +230,19 @@ namespace MobileGL::MG_Record { // still cuts a row wider than this, as it would for a slot). constexpr Uint32 kMonolithMaxReplyBytes = 0x7fffffffu; +#if MOBILEGL_PIPE_VERIFY + thread_local Bool t_portApplying = false; + struct PortApplyingScope { + PortApplyingScope() { t_portApplying = true; } + ~PortApplyingScope() { t_portApplying = false; } + }; +#endif + Bool ApplyOnMonolithPort(MG_Pipe::MGPWireOp op, const void* payload, const MG_Pipe::MGPipeVerbTail* tails, Uint32 tailCount, MG_Pipe::MGPipeReplySink* replies) { +#if MOBILEGL_PIPE_VERIFY + const PortApplyingScope applying; +#endif RecordVerbSink& sink = MonolithVerbSink(); MG_Backend::BackendObject* backend = MG_Backend::pActiveBackendObject.get(); if (sink.Backend() != backend) { @@ -1660,6 +1671,10 @@ namespace MobileGL::MG_Record { void ArmVerbControlKnobs() { ArmControlKnobs(); } +#if MOBILEGL_PIPE_VERIFY + Bool MonolithPortApplyingForVerify() { return t_portApplying; } +#endif + void SetVerbSessionResolver(VerbSessionResolver resolver) { g_verbSessionResolver = resolver; } void AssignVerbEmitters(MG_Backend::GlobalBackendFunctionsTable& table) { diff --git a/MobileGL/MG_Impl/Pipe/Verb/VerbPort.h b/MobileGL/MG_Impl/Pipe/Verb/VerbPort.h index 39c7a4d8..a46f05a0 100644 --- a/MobileGL/MG_Impl/Pipe/Verb/VerbPort.h +++ b/MobileGL/MG_Impl/Pipe/Verb/VerbPort.h @@ -58,6 +58,14 @@ namespace MobileGL::MG_Record { // The E2 control's per-frame evidence line, emitted only while a control is armed. void LogE2ControlLine(Uint64 frameOrdinal); +#if MOBILEGL_PIPE_VERIFY + // True while the monolith verb port applies a record on this thread. The verify read hook + // answers a pack-state read inside that window from the applied pack payload, as it does for a + // server-stamped verb: the record verb sink forces the neutral pack around its readback, so + // the live context is not the oracle there (PipeFill.cpp MGPipeVerifyReadHook). + Bool MonolithPortApplyingForVerify(); +#endif + // Called by the Fatal slots. Named separately so a death test can filter on it and so // that the message wording lives in exactly one place. [[noreturn]] void UnmigratedVerbFatal(const char* slot);