ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Madeira的总线处理器如何实现非对齐原子操作模拟:一个真实的正确性bug

Madeira的总线处理器如何实现非对齐原子操作模拟:一个真实的正确性bug Madeira的总线处理器如何实现非对齐原子操作模拟一个真实的正确性bug【免费下载链接】MadeiraRun x86-64 Windows PC games on jailed iOS via FEX-Emu Wine DXMT项目地址: https://gitcode.com/GitHub_Trending/mad/MadeiraMadeira是一个通过 FEX-Emu Wine DXMT 在越狱 iOS 上运行 x86-64 Windows PC 游戏的项目。在支持 32 位游戏的过程中团队踩中了一个真实的正确性 bugD3D9 的设备锁恰好骑在 16 字节边界上每一次LOCK指令都走 FEX 的**拆分校验split CAS**路径来模拟非对齐原子操作——而这条路径如果不加严格串行化计数器会丢更新甚至写出没有任何线程写过的值。 本文就用这个 bug 拆解 ARM64 上的原子操作模拟到底怎么做才对。为什么 32 位游戏会先撞上这个问题x86 架构里LOCK前缀的原子指令如LOCK CMPXCHG、LOCK XADD靠硬件总线锁/缓存行锁保证读-改-写不被打断。但有两个麻烦ARM64 没有等价机制iPhone 的 CPU 无法直接执行 x86 的LOCK语义FEX 必须在翻译层里用软件模拟——这就是文章标题里说的总线处理器部分FEXCore 中的 split CAS 助手函数DoCAS16/32/64位于 FEX 子模块的FEX/FEXCore/Source/Utils/ArchHelpers/Arm64.cpp。32 位 D3D9 的设备锁是非对齐的多个 32 位线程争抢的这块锁字可能落在 16 字节缓存行内的偏移 14处——一个 32 位字横跨两行高 2 字节在这一行低 2 字节在下一行。于是每次对该锁的LOCK CMPXCHG都走拆分开处理的路径。Madeira 之所以会大量触发这条路径是因为它支持未修改的 32 位 Windows 程序WoW64 方案详见 docs/WOW64.md。split CAS 路径非对齐原子操作是怎么模拟的当操作目标跨越 16 字节边界时FEX 的做法是把它拆开获取进程内 split-lock 锁严格模式下是唯一互斥量分别读取跨界的两半如偏移 12 的下半与偏移 16 的上半按 x86 语义完成比较/加法原子地写回两半释放锁竞争失败则重试。这套代码是上游 FEX 原样保留的测试文件 tests/host/check-d3d9-splitlock.py 会把DoCAS16/32/64逐字抽出到宿主机上编译验证覆盖三种真实形状设备锁字偏移 14 的 dword、偏移 12 的 64 位值、偏移 15 的 16 位值。真实的正确性 bug拆分会留下谁都没写过的值问题出在如果两个线程各自只锁定自己那一半、交错地写回缓存行最终会变成A 线程的低半 B 线程的高半——这个组合值没有任何线程写过且更新会丢失。这就是经典的 split-lock 正确性问题表现到游戏里就是 D3D9 设备锁自旋不释放dxmt 诊断日志会打[d3d9-lock-spin]对应MADEIRA_D9_LOCK_DIAG、MADEIRA_D9_LOCK_BACKOFF两个开关。值得强调的一点FEX 的 Arm64.cpp 里没有任何回滚路径——一旦写出撕裂值就无法恢复。所以正确的答案不是写错了再撤销而是根本不允许交错发生。验证脚本会显式断言回滚代码SplitCASRollback必须不存在。修复StrictInProcessSplitLocks 严格进程内互斥正确的解法是让所有split-lock 操作序列化在同一个严格进程内互斥量之下StrictInProcessSplitLocksFEX 的 WOW64 模块对 32 位 guest默认开启该配置且必须在上下文读取配置之前生效测试会断言这行代码的出现顺序对应开关MADEIRA_STRICT_SPLITLOCK默认on完整开关表见 docs/WOW64.md 第 8 节32 位进程的识别与启动路径在 app/Madeira/WineProcessBridge.m从 PE 头判定IMAGE_FILE_HEADER.Machine。四步验证80000 次拆分锁一个数都不能差tests/host/check-d3d9-splitlock.py 是纯宿主机测试不需要 iOS 设备四步走完诊断开关在位dxmt D3D9 前端与 i386 shim 中的诊断开关、日志标签齐全无回滚 默认严格FEX 无 split-lock 回滚路径WOW64 模块在 context 创建前应用严格默认值形状正确设备锁字比较失败时返回当前值且不写入跨界XADD的进位正确跨到高半相邻字节buf[12]、buf[13]、buf[18]、buf[19]分毫未动竞争下精确计数4 线程 × 20000 次拆分LOCK XADD在严格互斥下执行结果恰好等于 80000一个更新都不丢。整个测试以-fsanitizeaddress,undefined编译运行把正确性钉死在可重复验证的断言上。✅获取项目并复现git clone https://gitcode.com/GitHub_Trending/mad/Madeira cd Madeira python3 tests/host/check-d3d9-splitlock.py输出两行PASS即代表设备锁诊断在位、无回滚路径、split CAS 在真实设备锁形状下精确无误。小结关键点结论非对齐原子操作的根因32 位 D3D9 设备锁横跨 16 字节边界每次LOCK都触发 split CAS正确性风险无串行化时可能写出没有任何线程写过的撕裂值且不可回滚正确做法StrictInProcessSplitLocks全局严格互斥32 位 guest 默认开启验证手段逐字抽取 FEXCore 代码 4×20000 并发断言精确计数相关路径docs/WOW64.md、tests/host/check-d3d9-splitlock.py、app/Madeira/WineProcessBridge.m【免费下载链接】MadeiraRun x86-64 Windows PC games on jailed iOS via FEX-Emu Wine DXMT项目地址: https://gitcode.com/GitHub_Trending/mad/Madeira创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表