diff --git a/MobileGL/Config.h b/MobileGL/Config.h index 585834d1..e49f0d49 100644 --- a/MobileGL/Config.h +++ b/MobileGL/Config.h @@ -550,10 +550,6 @@ namespace MobileGL::MG_Config { // by design": no forced sync, so a one-frame respecify-and-draw loop grows without bound // and MagmaWireReclaimScenario's watermark cases must go red. Uint32 WireDeferredMb = 64; - // MOBILEGL_IPC_PERSISTENT_BLOCK_KB: block granularity of the persistent-map push. - // 0 IS A NEGATIVE CONTROL, NOT "unlimited": it disables the push, and - // PersistentCoherentMapScenario must go RED under it (exit gate E3(a)). - Uint32 PersistentBlockKb = 64; // MOBILEGL_IPC_PERSISTENT_HASH_SUPPRESS: 1 = the persistent-map push ships only // blocks whose xxHash64 changed since the last push, instead of the whole mapped // range every verb. 0 restores the whole-range push (A/B control). diff --git a/MobileGL/ConfigLoader.cpp b/MobileGL/ConfigLoader.cpp index b8387cb9..7700f8be 100644 --- a/MobileGL/ConfigLoader.cpp +++ b/MobileGL/ConfigLoader.cpp @@ -714,11 +714,11 @@ namespace MobileGL::MG_ConfigLoader { // changes the wall clock by seconds (the P12 sweep: 28.3 s at 1 down to 10.8 s at 6) a // log that does not name it makes every run ambiguous about its own configuration. MGLOG_I("Config: IPC ring=%uMiB stage=%uMiB wire-deferred=%uMiB spin=%uus event-wait=%ums " - "persistent-block=%uKiB create-window=%u pbo-readback-sync=%u poll-escalate=%u " + "create-window=%u pbo-readback-sync=%u poll-escalate=%u " "adopt-tier=%s allow-t0=%u run-ahead=%u present-credit=%u control-timeout=%ums " "cold-start=%ums strict=%d audit=%d role-split-state=%d affinity='%s' surface=%s", ipc.RingMb, ipc.StageMb, MG_Config::RecordArm.WireDeferredMb, ipc.SpinUs, ipc.EventWaitMs, - MG_Config::RecordArm.PersistentBlockKb, ipc.CreateWindow, ipc.PboReadbackSync, ipc.PollEscalate, + ipc.CreateWindow, ipc.PboReadbackSync, ipc.PollEscalate, ipc.AdoptTier == 0 ? "0" : ipc.AdoptTier == 1 ? "1" : ipc.AdoptTier == 2 ? "2" @@ -735,9 +735,6 @@ namespace MobileGL::MG_ConfigLoader { // P7 wave 4 M2 (Config.h has the semantics). 0 is admitted ON PURPOSE as the negative // control: no forced sync, and MagmaWireReclaimScenario's watermark case must go red. ipc.WireDeferredMb = QueryEnvUint32("MOBILEGL_IPC_WIRE_DEFERRED_MB", 64, 0, 65536); - // 0 is admitted ON PURPOSE and is the negative control of exit gate E3(a): it turns - // the persistent-map push OFF, and PersistentCoherentMapScenario must go red. - ipc.PersistentBlockKb = QueryEnvUint32("MOBILEGL_IPC_PERSISTENT_BLOCK_KB", 64, 0, 65536); // Whole-range push is the 0 arm; with it on (default) only blocks whose // xxHash64 changed since the last push are shipped. ipc.PersistentHashSuppress = QueryEnvUint32("MOBILEGL_IPC_PERSISTENT_HASH_SUPPRESS", 1, 0, 1); @@ -751,10 +748,6 @@ namespace MobileGL::MG_ConfigLoader { "server never forces a sync for orphaned wire buffer stores, so a long frame " "that respecifies and draws holds every one of them until the frame ends"); } - if (ipc.PersistentBlockKb == 0) { - MGLOG_W("Config: MOBILEGL_IPC_PERSISTENT_BLOCK_KB=0 is the E3(a) NEGATIVE CONTROL: " - "the persistent-map push is OFF and a coherent-map scenario must go red"); - } } void Init() { diff --git a/MobileGL/MG_IntegrationTest/Scenarios/PersistentCoherentMapScenario.cpp b/MobileGL/MG_IntegrationTest/Scenarios/PersistentCoherentMapScenario.cpp index a77eb738..7d52226e 100644 --- a/MobileGL/MG_IntegrationTest/Scenarios/PersistentCoherentMapScenario.cpp +++ b/MobileGL/MG_IntegrationTest/Scenarios/PersistentCoherentMapScenario.cpp @@ -593,11 +593,9 @@ void main() { oColor = vec4(vColor, 1.0); } "a window with " << kDrawsInTheWindow << " writes and as many draws through a live coherent mapping cannot have pushed " - "zero bytes. Zero here with MOBILEGL_IPC_PERSISTENT_BLOCK_KB at its default " - "means the push is not reaching this buffer - which is a DIFFERENT defect from " - "the store having been adopted, and the arm assertion above has already ruled " - "that one out. Zero with the knob set to 0 is exit gate E3(a)'s negative control " - "working as intended. Line: " + "zero bytes. Zero here means the push is not reaching this buffer - which is a " + "DIFFERENT defect from the store having been adopted, and the arm assertion " + "above has already ruled that one out. Line: " << window.line; } else { // Recorded, not asserted: on this arm the number is whatever the driver's adoption diff --git a/MobileGL/MG_State/GLState/BufferState/BufferObject.cpp b/MobileGL/MG_State/GLState/BufferState/BufferObject.cpp index cf8f7627..ae4e631c 100644 --- a/MobileGL/MG_State/GLState/BufferState/BufferObject.cpp +++ b/MobileGL/MG_State/GLState/BufferState/BufferObject.cpp @@ -501,14 +501,7 @@ namespace MobileGL::MG_State::GLState { // carries are real, current and the cheapest honest ones there are. A zero-length // record would have been the alternative and it is illegal by contract rule A. if (m_size == 0) return; - const Uint64 blockBytes = MG_Record::PersistentMapTracker::BlockBytes(); - // MOBILEGL_IPC_PERSISTENT_BLOCK_KB=0 TURNS THE WHOLE MECHANISM OFF, STATE RECORD - // INCLUDED (E3(a)). An earlier cut skipped the blocks and still shipped a whole buffer - // here, which meant an unmap delivered the bytes the control exists to withhold - and - // a negative control that still delivers them is not a control. With the knob at 0 - // nothing is published and nothing is pushed, so the probe answers clean, the frame - // draws the last uploaded bytes, and PersistentCoherentMapScenario goes red. - if (blockBytes == 0) return; + constexpr Uint64 blockBytes = MG_Record::PersistentMapTracker::BlockBytes(); const SizeT length = blockBytes >= static_cast(m_size) ? m_size : static_cast(blockBytes); NotifySubData(0, length); } diff --git a/MobileGL/MG_State/GLState/BufferState/BufferObject.h b/MobileGL/MG_State/GLState/BufferState/BufferObject.h index 4bd69e94..d32e7e51 100644 --- a/MobileGL/MG_State/GLState/BufferState/BufferObject.h +++ b/MobileGL/MG_State/GLState/BufferState/BufferObject.h @@ -150,7 +150,7 @@ namespace MobileGL { // behaviour and D-J forbids it. The pull build compiles none of it, which is also // how G1 holds over a file this central. - // ONE MOBILEGL_IPC_PERSISTENT_BLOCK_KB BLOCK of the mapped span, emitted through + // ONE BLOCK of the mapped span (PersistentMapTracker::BlockBytes), emitted through // the private NotifySubData - the same serial, the same defined-content flag, the // same record - so the split arm and the monolith arm differ in HOW the span is // cut and in nothing else. Called only by diff --git a/MobileGL/MG_State/GLState/BufferState/PersistentMapTracker.cpp b/MobileGL/MG_State/GLState/BufferState/PersistentMapTracker.cpp index 81b629bc..2281c44e 100644 --- a/MobileGL/MG_State/GLState/BufferState/PersistentMapTracker.cpp +++ b/MobileGL/MG_State/GLState/BufferState/PersistentMapTracker.cpp @@ -724,10 +724,6 @@ namespace MobileGL::MG_Record { return *instance; } - Uint64 PersistentMapTracker::BlockBytes() { - return static_cast(MG_Config::RecordArm.PersistentBlockKb) * 1024ull; - } - Bool PersistentMapTracker::PushIsArmed() { // P13 W4a: the record arm's buffer reads never ask the frontend object to sync a map, so // the client pushes the mapped span wherever that arm runs - monolith's included. @@ -908,33 +904,7 @@ namespace MobileGL::MG_Record { Forget(buffer); return; } - const Uint64 blockBytes = BlockBytes(); - // 0 IS THE NEGATIVE CONTROL, NOT "unlimited" (E3(a)). Pushing one whole-span block - // here would make the control green for the wrong reason - it has to disable the - // push, so that PersistentCoherentMapScenario draws the last uploaded bytes and goes - // red exactly the way an unpushed map does. - // - // AND IT SAYS SO, ONCE. Until now this was a silent `return`, so E3(a)'s red could - // only ever be the scenario's pixel assertion and the control had no way to tell "the - // push was disabled" apart from "the push was never armed, or never reached, or the - // knob never got here" (joint-v1.md §3: "There is no Fatal for block size zero"; - // ID-65 assigns the line to x2). The control now requires BOTH: the pixel red AND - // this line in the entry's own private log. It is MGLOG_W and not a Fatal because 0 - // is a legal configured value whose whole purpose is to keep running with the push - // off; aborting here would turn every E3(a) entry into a subprocess abort and take - // the pixel evidence with it. - if (blockBytes == 0) { - if (!m_blockZeroAnnounced) { - m_blockZeroAnnounced = true; - MGLOG_W("MGPipe: persistent-map push disabled - MOBILEGL_IPC_PERSISTENT_BLOCK_KB=0 " - "is exit gate E3(a)'s NEGATIVE CONTROL, not 'unlimited': a live " - "persistent WRITE mapping's dirty blocks are NOT being pushed, so the " - "server draws whatever bytes last crossed by some other route. A lane " - "that stays green with this set is not getting its pixels from the push"); - } - return; - } - + constexpr Uint64 blockBytes = BlockBytes(); const auto range = buffer.GetMappedRange(); const Uint64 begin = static_cast(range.start); const Uint64 end = static_cast(range.end); @@ -1077,15 +1047,12 @@ namespace MobileGL::MG_Record { if (shadow != nullptr) { state = &m_blockHashes[buffer.GetLifetimeId()]; const Uint64 blockCount = (end - begin + blockBytes - 1) / blockBytes; - // A remap, a resize or a block-size change invalidates the layout the - // hashes were taken against: reset, which forces one full push - the - // conservative answer for a new layout. - if (state->begin != begin || state->end != end || state->blockBytes != blockBytes || - state->hashes.size() != blockCount) { + // A remap or a resize invalidates the layout the hashes were taken against: + // reset, which forces one full push - the conservative answer for a new layout. + if (state->begin != begin || state->end != end || state->hashes.size() != blockCount) { *state = {}; state->begin = begin; state->end = end; - state->blockBytes = blockBytes; state->hashes.assign(static_cast(blockCount), 0); } } diff --git a/MobileGL/MG_State/GLState/BufferState/PersistentMapTracker.h b/MobileGL/MG_State/GLState/BufferState/PersistentMapTracker.h index 9a9a2987..266e6169 100644 --- a/MobileGL/MG_State/GLState/BufferState/PersistentMapTracker.h +++ b/MobileGL/MG_State/GLState/BufferState/PersistentMapTracker.h @@ -28,14 +28,11 @@ // pushing, and the two arms diverge with no test able to say so. IsLivePersistentMap() is the // single spelling; BufferObject::SyncPersistentMappedRange is held to it by a unit case. // -// THE GRANULARITY. MOBILEGL_IPC_PERSISTENT_BLOCK_KB (default 64) blocks, keyed -// {MGPipeHandle, blockIndex} - the key is implicit, because a block ships as an ORDINARY -// resource_subdata record whose destination range is [blockIndex * blockBytes, + blockBytes). -// NO NEW RECORD KIND: the existing record is already chunked by -// MGPipeForEachSubDataRecordRange and already acceptance-gated, and a second way to say -// "these bytes go there" is a second way to get it wrong. A block size of 0 is E3(a)'s -// NEGATIVE CONTROL and means "push nothing" - not "one unlimited block" - so -// PersistentCoherentMapScenario must go red under it. +// THE GRANULARITY. 64 KiB blocks (BlockBytes()), keyed {MGPipeHandle, blockIndex} - the key +// is implicit, because a block ships as an ORDINARY resource_subdata record whose destination +// range is [blockIndex * blockBytes, + blockBytes). NO NEW RECORD KIND: the existing record is +// already chunked by MGPipeForEachSubDataRecordRange and already acceptance-gated, and a second +// way to say "these bytes go there" is a second way to get it wrong. // // Only changed blocks ship. At each validate point a member pushes just the blocks written // since its last push. A map the mprotect write-fault tracker holds (MOBILEGL_PIPE_PERSISTENT_MPROTECT; @@ -101,8 +98,8 @@ namespace MobileGL::MG_Record { // client-exclusive). Leaks at exit for ID-8's reason, once per role-local singleton. static PersistentMapTracker& Instance(); - // MOBILEGL_IPC_PERSISTENT_BLOCK_KB * 1024. Zero means the push is OFF (E3(a)). - static Uint64 BlockBytes(); + // The push's block size (THE GRANULARITY above). + static constexpr Uint64 BlockBytes() { return 64ull * 1024ull; } // Transport != Monolith. The whole module is inert on the monolith path: an extra // resource_subdata record there would be new behaviour, which D-J forbids. static Bool PushIsArmed(); @@ -154,7 +151,6 @@ namespace MobileGL::MG_Record { void ResetCountersForTest() { m_blocksPushed = 0; m_bytesPushed = 0; - m_blockZeroAnnounced = false; } // Unit tests only: clears the membership, the hash cache and the mprotect tracked // slots (restoring every tracked page writable first), and resets the counters. @@ -225,7 +221,6 @@ namespace MobileGL::MG_Record { struct BlockHashState { Uint64 begin = 0; Uint64 end = 0; - Uint64 blockBytes = 0; Vector hashes; }; UnorderedMap m_blockHashes; @@ -252,11 +247,6 @@ namespace MobileGL::MG_Record { // ran them once (the two Members hooks) - the guard's thread-local read was a // measurable per-buffer-per-draw cost on the emutls path. void PushBlocksForChecked(MG_State::GLState::BufferObject& buffer); - // E3(a)'s diagnostic is emitted ONCE per process. PushBlocksFor runs at every validate - // point of every member, so an unlatched MGLOG_W would be one line per draw per mapping - // - and a control that has to grep a log cannot tell a message that fired from a - // message that flooded. - Bool m_blockZeroAnnounced = false; }; // What the client's emit table calls immediately BEFORE emitting any verb that can read a diff --git a/MobileGL/MG_Test/Buffer/SplitBufferTest.cpp b/MobileGL/MG_Test/Buffer/SplitBufferTest.cpp index 7b7d7ce8..12eac427 100644 --- a/MobileGL/MG_Test/Buffer/SplitBufferTest.cpp +++ b/MobileGL/MG_Test/Buffer/SplitBufferTest.cpp @@ -86,13 +86,11 @@ namespace { protected: void SetUp() override { m_transport = MG_Config::Transport; - m_blockKb = MG_Config::RecordArm.PersistentBlockKb; m_adoptTier = MG_Config::Ipc.AdoptTier; m_pipeStats = MG_Config::Features.PipeStats; m_context = MG_State::pGLContext.Take(); MG_State::pGLContext = MakeUnique(); MG_Config::Transport = MG_Config::TransportMode::InProcess; - MG_Config::RecordArm.PersistentBlockKb = 64; MG_Config::Ipc.AdoptTier = 2; MG_Config::Features.PipeStats = true; MG_Util::PipeStats::Init(); @@ -108,7 +106,6 @@ namespace { PersistentMapTracker::Instance().ClearForTest(); MG_State::pGLContext = Move(m_context); MG_Config::Transport = m_transport; - MG_Config::RecordArm.PersistentBlockKb = m_blockKb; MG_Config::Ipc.AdoptTier = m_adoptTier; MG_Config::Features.PipeStats = m_pipeStats; MG_Util::PipeStats::Init(); @@ -121,7 +118,6 @@ namespace { } MG_Config::TransportMode m_transport = MG_Config::TransportMode::Monolith; - Uint32 m_blockKb = 64; Uint32 m_adoptTier = 2; Bool m_pipeStats = false; SharedPtr m_context; @@ -463,35 +459,6 @@ TEST_F(SplitBufferSet, BothEdgesOfAWriteMapPublishOneStateRecord) { "the second the record stays dirty for the buffer's life"; } -// E3(a)'s NEGATIVE CONTROL: 0 disables the push, it does not mean "one unlimited block" - and -// it disables the STATE RECORDS with it. An earlier cut skipped the blocks and still shipped a -// whole buffer at unmap, so a scenario that unmapped before reading back went green and the -// control was dead. -TEST_F(SplitBufferSet, AZeroBlockSizeTurnsThePushOffRatherThanMakingItUnlimited) { - MG_Config::RecordArm.PersistentBlockKb = 0; - constexpr SizeT kSize = 128u * 1024u; - auto buffer = MakeBuffer(23u, kSize); - - const Uint64 beforeMap = buffer->GetChangeSerial(); - buffer->AcquireMemoryRange(Range1D{0, kSize}, BufferMappingAccessBit::Write | BufferMappingAccessBit::Persistent); - ASSERT_TRUE(PersistentMapTracker::IsLivePersistentMap(*buffer)); - EXPECT_EQ(buffer->GetChangeSerial(), beforeMap) << "the rising-edge state record went out with the push disabled"; - - const Uint64 before = MG_Util::PipeStats::TotalBytes(MG_Util::PipeStats::ByteClass::PersistentMapPush); - MG_Record::PushPersistentMapsBeforeVerb(); - EXPECT_EQ(PersistentMapTracker::Instance().BlocksPushed(), 0u); - EXPECT_EQ(MG_Util::PipeStats::TotalBytes(MG_Util::PipeStats::ByteClass::PersistentMapPush), before) - << "MOBILEGL_IPC_PERSISTENT_BLOCK_KB=0 must ship nothing, so that " - "PersistentCoherentMapScenario goes red under it"; - - const Uint64 beforeUnmap = buffer->GetChangeSerial(); - buffer->ReleaseMemory(/*landStagedWrites=*/true); - EXPECT_EQ(buffer->GetChangeSerial(), beforeUnmap + 1) - << "with the push off the unmap must emit only its own NotifyFlushMappedRange - a " - "falling-edge record here delivers a whole buffer the control exists to withhold, " - "and a negative control that still delivers the bytes is not a control"; -} - // The set does not keep a pointer to a dead buffer. TEST_F(SplitBufferSet, ADestroyedBufferLeavesTheSet) { { @@ -871,9 +838,6 @@ TEST(SplitBufferSet, TheLastBlockIsTheRemainderAndNotAWholeBlock) { TEST(SplitBufferSet, BothEdgesOfAWriteMapPublishOneStateRecord) { MGL_SPLIT_ONLY_OR_SKIP(); } -TEST(SplitBufferSet, AZeroBlockSizeTurnsThePushOffRatherThanMakingItUnlimited) { - MGL_SPLIT_ONLY_OR_SKIP(); -} TEST(SplitBufferSet, ADestroyedBufferLeavesTheSet) { MGL_SPLIT_ONLY_OR_SKIP(); } diff --git a/MobileGL/MG_Test/SanityTest.cpp b/MobileGL/MG_Test/SanityTest.cpp index 67454eb6..a6d1f52d 100644 --- a/MobileGL/MG_Test/SanityTest.cpp +++ b/MobileGL/MG_Test/SanityTest.cpp @@ -4326,12 +4326,10 @@ TEST(DirectGLESBufferDrawProbe, UnderSplitTheRecordAloneAnswersTheLiveHostMapQue // case reaches is optional. const Uint64 previousPush = MG_Config::Features.PipePush; const auto previousTransport = MG_Config::Transport; - const Uint32 previousBlockKb = MG_Config::RecordArm.PersistentBlockKb; MG_Pipe::MGPipeResourceOps ops{}; MG_Config::Features.PipePush |= MG_Pipe::kMGPipeSubsystemResources; MG_Pipe::MGPipeSetResourceOps(&ops); MG_Config::Transport = MG_Config::TransportMode::InProcess; - MG_Config::RecordArm.PersistentBlockKb = 64; // P5 c1 / R-8: UNDER SPLIT THE OP TABLE IS NO LONGER THE ARMING CONDITION, and this case is // the first place that shows. `MGPipeSetResourceOps(&ops)` is the SERVER's registration; the // client's liveness gate now reads the caps mirror's consumer mask instead, because under a @@ -4424,7 +4422,6 @@ TEST(DirectGLESBufferDrawProbe, UnderSplitTheRecordAloneAnswersTheLiveHostMapQue BufferImpl::g_backendBufferResources.ReleaseByHandle(res); } - MG_Config::RecordArm.PersistentBlockKb = previousBlockKb; MG_Config::Transport = previousTransport; MG_Pipe::MGPipeSetResourceOps(nullptr); MG_Config::Features.PipePush = previousPush; diff --git a/MobileGL/MG_Util/Metrics/PipeStats.cpp b/MobileGL/MG_Util/Metrics/PipeStats.cpp index e624a4d3..2f3c1dd1 100644 --- a/MobileGL/MG_Util/Metrics/PipeStats.cpp +++ b/MobileGL/MG_Util/Metrics/PipeStats.cpp @@ -79,8 +79,8 @@ // per sub-draw), so this class is Espryt-only by construction. // persistent-map-push WIRED IN P5 (b1), and only a split build can ever move it. The one // site is BufferObject::PushMappedSpanBlock, i.e. the client shipping -// one MOBILEGL_IPC_PERSISTENT_BLOCK_KB block of a persistently mapped -// span because MGPipeApplyMapPersistent declined the adoption (R-6, +// one 64 KiB block of a persistently mapped span because +// MGPipeApplyMapPersistent declined the adoption (R-6, // tier T2). Zero in every monolith build, and that zero is CORRECT // rather than missing: a persistent map there is a permanent address // space donation (D4/D-B4), the application writes straight into GPU diff --git a/docs/Disaggregated/design/07-memory-readback-verification.md b/docs/Disaggregated/design/07-memory-readback-verification.md index 975ea53b..9c52eab5 100644 --- a/docs/Disaggregated/design/07-memory-readback-verification.md +++ b/docs/Disaggregated/design/07-memory-readback-verification.md @@ -12,7 +12,7 @@ | T1 | server 导出 opaque fd | 仅 Adreno 的 Vulkan 路径 | | T2 | 拒绝,client 侧推送 | 永久正确回退;**今天 split 用的档**(`MOBILEGL_IPC_ADOPT_TIER=2`),stream 数据面上强制(P11 A1:两端握手时 `Transport::SettleAdoptTierAtHandshake` 对 0/1 打一行 `Refuse{AdoptTierOnStream}` 并走 T2;共享段上 client 握手期 `Fatal{UnimplementedAdoptTier}`,[`CONTRACT-P11.md`](../../archive/contracts/CONTRACT-P11.md) §1) | -T2 下 client 侧推送三件套:不做 map/unmap 命令对(payload 带 `hasLiveHostWrites`);在每个 validate 点按块(`MOBILEGL_IPC_PERSISTENT_BLOCK_KB`,默认 64)推送可达的已映射 buffer,脏页追踪 + 哈希抑制只发变化的块(P5d);门 `PersistentCoherentMapScenario`。`mpr` 数的是每一次 `MapPersistent` 发射(铸成或拒绝都算),所以在 monolith 下也可断言。 +T2 下 client 侧推送三件套:不做 map/unmap 命令对(payload 带 `hasLiveHostWrites`);在每个 validate 点按 64 KiB 块推送可达的已映射 buffer,脏页追踪 + 哈希抑制只发变化的块(P5d);门 `PersistentCoherentMapScenario`。`mpr` 数的是每一次 `MapPersistent` 发射(铸成或拒绝都算),所以在 monolith 下也可断言。 ### 12.1 采纳档的握手期结算 diff --git a/docs/Disaggregated/design/09-build-switches-counters.md b/docs/Disaggregated/design/09-build-switches-counters.md index 336a30f9..c2815ec7 100644 --- a/docs/Disaggregated/design/09-build-switches-counters.md +++ b/docs/Disaggregated/design/09-build-switches-counters.md @@ -70,7 +70,7 @@ CMake:`MOBILEGL_BUILD_DISAGGREGATED`(OFF)、`MOBILEGL_BUILD_DISAGGREGATED_ | `MOBILEGL_IPC_BATCH_WAITS` | 1 | lockstep 下值类记录发布即返回;verify 强制 0 | | `MOBILEGL_IPC_EVENT_WAIT_MS` | 2000 | 反向事件遇满环时 server 等 client 排空的整笔预算(§11.7) | | `MOBILEGL_IPC_WIRE_DEFERRED_MB` | 64 | Magma wire 臂延迟回收的水位线;`0` 是 M2 阴性对照 | -| `MOBILEGL_IPC_PERSISTENT_BLOCK_KB` / `_PERSISTENT_HASH_SUPPRESS` | 64 / 1 | persistent-map 推送粒度 / 只推变化的块;`0` 是对照 | +| `MOBILEGL_IPC_PERSISTENT_HASH_SUPPRESS` | 1 | persistent-map 推送只推变化的块(粒度固定 64 KiB,`PersistentMapTracker::BlockBytes()`);`0` 是整段推送的 A/B 对照 | | `MOBILEGL_IPC_ADOPT_TIER` | 未设 = T0 | 未设(用户 2026-09-29 定为缺省)= 能用就 T0,不能用(stream、无 AHB、POST 失败、server 不允许)安静回退 T2:只 MGLOG_D、照样计数;`0` = 点名要 T0,回退有具名行(A1 的 `Refuse{AdoptTierOnStream}` 等);`1` = T1 已关,具名拒绝后 T2;`2` = T2(P11 前的缺省)。`CONTRACT-P11.md` B2 | | `MOBILEGL_IPC_ALLOW_ADOPT_T0` | 1 | server 自有:`0` = 永不批准 T0(会话走 T2),经 `ServerSpawn` 保留 | | `MOBILEGL_IPC_STRICT_ERRORS` / `MOBILEGL_IPC_AUDIT` / `MOBILEGL_IPC_ROLE_SPLIT_STATE` | 0 / 0 / 1 | 残余输入读升级为 Fatal / 退休 staging 填 `0xDD` / 双块(P5f;P15 起默认开,`0` 关闭,阴性对照显式设 0;双块下 barriered fill 写 client 块,不再 quiesce applier) | diff --git a/docs/ci/ci-cleanup-log.md b/docs/ci/ci-cleanup-log.md index cae0f090..8523adc2 100644 --- a/docs/ci/ci-cleanup-log.md +++ b/docs/ci/ci-cleanup-log.md @@ -58,6 +58,7 @@ them wrong. | 2026-10-18 | `scripts/ci/wait_boundary_negative_control.py` | Test / `integration-split` | E1's body inside the step above: the three boundary cases rerun with the barrier off | `RemoteWaitBoundaryControl.AnUnwaitedPublishIsSeenAsNoWait`: the same ApplierReset published with no wait must read parked=0, the observation the owed waits read as parked=1 | | 2026-10-18 | `scripts/ci/control_smoke_test.sh`, `scripts/ci/testdata/stub_ctest.sh`, `scripts/ci/testdata/split_private_log_smoke.sh`, and the `reset` / `results` / `assertion` / `evidence` modes of `split_log_paths.py` | Test / pipe-gates (R-16) | smoke cases and helpers of the step above only | none needed | | 2026-10-18 | unit `RemoteRunAhead.ClearingTheVerbBarrierDisarmsRunAheadEvenWithTheCapBit`, and the `MOBILEGL_IPC_VERB_BARRIER` knob with its arm in the shipped client (`ClientSession`: the free-running `EmitAndWaitTails` return, the run-ahead latch term, the `gPipeInputs` guard's early return, the `verb-barrier=` field of the `Config: IPC` line) | Test / unit (split); product code | `0` was never a product mode, only E1's negative control, retired above; the unit case pinned that the control also disarmed run-ahead | `RemoteWaitBoundaryControl.AnUnwaitedPublishIsSeenAsNoWait`; `MOBILEGL_IPC_RUN_AHEAD=0` stays the lockstep A/B arm | +| 2026-10-18 | unit `SplitBufferSet.AZeroBlockSizeTurnsThePushOffRatherThanMakingItUnlimited` (and its skip stub in the non-disaggregated half), and the `MOBILEGL_IPC_PERSISTENT_BLOCK_KB` knob with its `0` arm in the shipped tracker (`PersistentMapTracker::PushBlocksForChecked`'s early return and once-per-process warning, `BufferObject::NotePersistentMapStateChanged`'s, the `persistent-block=` field of the `Config: IPC` line) | Test / unit; product code | `0` was never a product mode, only E3(a)'s negative control, retired above; the unit case pinned that `0` shipped nothing; the block size is now the constant 64 KiB (`PersistentMapTracker::BlockBytes()`) | `PersistentCoherentMapScenario.ThePushIsTheOnlyRouteAWriteTakesToTheServer` | ## Kept after investigation diff --git a/scripts/data/skip_census_baseline.json b/scripts/data/skip_census_baseline.json index 30305f2c..0c8afaa8 100644 --- a/scripts/data/skip_census_baseline.json +++ b/scripts/data/skip_census_baseline.json @@ -11624,7 +11624,6 @@ "SplitBufferSet.AFaultedMapTheDrawDidNotBindStillShipsBeforeTheDrawThatDoes", "SplitBufferSet.AShadowThatFailsThePageGranularTestKeepsTheInwardAlignmentAndItsEdges", "SplitBufferSet.ASubPageMapIsOneProtectedPageAndAWriteThroughItFaults", - "SplitBufferSet.AZeroBlockSizeTurnsThePushOffRatherThanMakingItUnlimited", "SplitBufferSet.BothEdgesOfAWriteMapPublishOneStateRecord", "SplitBufferSet.MembershipIsSyncPersistentMappedRangesOwnEarlyOutChain", "SplitBufferSet.Row0EverySsboBindingPointIsMarkedByADraw", @@ -15948,7 +15947,6 @@ "SplitBufferSet.AFaultedMapTheDrawDidNotBindStillShipsBeforeTheDrawThatDoes", "SplitBufferSet.AShadowThatFailsThePageGranularTestKeepsTheInwardAlignmentAndItsEdges", "SplitBufferSet.ASubPageMapIsOneProtectedPageAndAWriteThroughItFaults", - "SplitBufferSet.AZeroBlockSizeTurnsThePushOffRatherThanMakingItUnlimited", "SplitBufferSet.AnOlderWritebackCannotRetireANewerGpuWriteMark", "SplitBufferSet.BothEdgesOfAWriteMapPublishOneStateRecord", "SplitBufferSet.MembershipIsSyncPersistentMappedRangesOwnEarlyOutChain", @@ -17437,7 +17435,6 @@ "SplitBufferSet.AFaultedMapTheDrawDidNotBindStillShipsBeforeTheDrawThatDoes", "SplitBufferSet.AShadowThatFailsThePageGranularTestKeepsTheInwardAlignmentAndItsEdges", "SplitBufferSet.ASubPageMapIsOneProtectedPageAndAWriteThroughItFaults", - "SplitBufferSet.AZeroBlockSizeTurnsThePushOffRatherThanMakingItUnlimited", "SplitBufferSet.AnOlderWritebackCannotRetireANewerGpuWriteMark", "SplitBufferSet.BothEdgesOfAWriteMapPublishOneStateRecord", "SplitBufferSet.MembershipIsSyncPersistentMappedRangesOwnEarlyOutChain",