[Feat] (P13 W4): MG_Config::DataArmIsRecord and the W4-W6 MOBILEGL_PIPE_DATA_ARM knob

This commit is contained in:
2026-10-06 08:14:36 -04:00
parent a32ca0017d
commit 081854653a
4 changed files with 56 additions and 0 deletions
+23
View File
@@ -735,10 +735,33 @@ namespace MobileGL::MG_Config {
inline Bool ServerOwnedWindowSurfaces() {
return Transport == TransportMode::Spawn && Ipc.Surface == IpcSurface::Server;
}
// P13 W4: THE DATA-ARM QUESTION - do the backends read RECORDS (the applier's twins, the staged
// stores, the verb's own handles) rather than frontend objects? Under a wire the answer has
// always been yes; P13 makes it yes for monolith too ("monolith is the push variant"), one
// record family at a time. Each family's arm sites ask THIS rather than `Transport`, which
// keeps answering the questions that really are about the transport (lifecycle, roles, whose
// caps, whether a store copies).
//
// MOBILEGL_PIPE_DATA_ARM=record (default) | frontend picks monolith's arm for the families
// already switched. It exists for W4-W6 only - bisecting a monolith red to the switch, and
// the per-thread CPU record (ID-P13-2) - and goes in W6 with the frontend arms. Latched once
// by MG_ConfigLoader::Init(): the two arms keep their twins in different places.
extern Bool MonolithTakesRecordArm;
inline Bool DataArmIsRecord() { return Transport != TransportMode::Monolith || MonolithTakesRecordArm; }
// ...and the record arm runs in this process over stores that ALIAS the frontend's shadows
// (monolith) instead of copying them (every wire).
inline Bool RecordArmAliasesFrontend() {
return Transport == TransportMode::Monolith && MonolithTakesRecordArm;
}
#else
// The whole point: in a build without MG_Remote this folds at compile time, so
// `if (MG_Config::Transport != MG_Config::TransportMode::Monolith)` in Init.cpp is a
// discarded statement and the pull build gains no symbol, no branch and no byte.
inline constexpr TransportMode Transport = TransportMode::Monolith;
// P13 W4: a build without MG_Remote stays on the frontend arm until W5 moves the record arm
// out of the disaggregated gating (ID-P13-1 / A2).
inline constexpr Bool DataArmIsRecord() { return false; }
inline constexpr Bool RecordArmAliasesFrontend() { return false; }
#endif
} // namespace MobileGL::MG_Config
+29
View File
@@ -38,6 +38,7 @@ namespace MobileGL::MG_Config {
String TransportEndpoint;
Bool SplitTransportRequestedByConfig = false;
IpcTable Ipc;
Bool MonolithTakesRecordArm = true;
#endif
} // namespace MobileGL::MG_Config
@@ -455,6 +456,33 @@ namespace MobileGL::MG_ConfigLoader {
// rather than silent, because the failure this avoids is a P6 lane that set
// MOBILEGL_TRANSPORT=spawn, fell back to monolith, and went green on the wrong arm.
// The mode is left at Monolith so nothing half-initializes.
// P13 W4 (Config.h DataArmIsRecord). Read after InitTransport: `frontend` names monolith's
// arm only - a wire has no frontend objects on its server half to read, so there it is
// ignored by name rather than half-honoured.
inline void InitDataArm() {
String value;
QueryEnvVariable("MOBILEGL_PIPE_DATA_ARM", value, "record");
String lowered = value;
std::transform(lowered.begin(), lowered.end(), lowered.begin(),
[](unsigned char c) { return static_cast<char>(std::tolower(c)); });
MG_Config::MonolithTakesRecordArm = true;
if (lowered.empty() || lowered == "record") return;
if (lowered == "frontend") {
if (MG_Config::Transport != MG_Config::TransportMode::Monolith) {
MGLOG_W("Config: MOBILEGL_PIPE_DATA_ARM=frontend is ignored under a transport - the "
"record arm is the only arm a wire has");
return;
}
MG_Config::MonolithTakesRecordArm = false;
MGLOG_I("Config: MOBILEGL_PIPE_DATA_ARM=frontend - monolith reads frontend objects in "
"the record families switched so far");
return;
}
MGLOG_W("Config: Ignoring invalid env variable MOBILEGL_PIPE_DATA_ARM='%s'; expected "
"record|frontend, using record",
value.c_str());
}
inline void InitTransport() {
String value;
QueryEnvVariable("MOBILEGL_TRANSPORT", value, "monolith");
@@ -702,6 +730,7 @@ namespace MobileGL::MG_ConfigLoader {
// After InitFeatures, so the one line InitIpc logs is the last word on this run's
// configuration, and before the accepted-env map is destroyed just below.
InitTransport();
InitDataArm();
InitIpc();
#endif
@@ -128,6 +128,7 @@ namespace MGITest {
default: state.transportName = "non-monolith"; break;
}
state.transportResolved = MobileGL::MG_Config::Transport != TransportMode::Monolith;
state.dataArmIsRecord = MobileGL::MG_Config::DataArmIsRecord();
// Active() is c0's one deliberately non-aborting accessor: "does a session exist" has a
// legitimate no. Everything below it is only reached through a live session, so nothing
@@ -63,6 +63,9 @@ namespace MGITest {
bool transportResolved = false;
// The resolved transport, for a message: "monolith", "inproc", "spawn", "unix", "pipe".
std::string transportName = "monolith";
// P13 W4: MG_Config::DataArmIsRecord() - false in a build without the peek (and without
// MG_Remote), which stays on the frontend arm until W5.
bool dataArmIsRecord = false;
// ClientSession::Active() != nullptr.
bool sessionActive = false;
// ImplementedVerbCount(), out of kRemoteEmitSlotCount (71).