ReactOS 硬件资源仲裁器 (Arbiter) 完整实现计划

ReactOS 硬件资源仲裁器 (Arbiter) 完整实现计划

概述

本计划目标是以增量方式完整实现 sdk/lib/drivers/arbiter/arbiter.c 的全部 21 个函数,并更新所有调用方以正确使用仲裁器功能。当前该库仅有 ArbInitializeArbiterInstance 完成实现,其余 20 个函数均为 UNIMPLEMENTED 存根。


当前状态分析

已实现的基础设施

  • RTL Range List (sdk/lib/rtl/rangelist.c): 完整可用,提供 RtlAddRangeRtlFindRangeRtlDeleteRangeRtlInvertRangeListRtlIsRangeAvailableRtlMergeRangeLists
  • 数据结构 (sdk/lib/drivers/arbiter/arbiter.h): ARBITER_INSTANCEARBITER_ALLOCATION_STATEARBITER_ORDERING_LISTARBITER_ALTERNATIVE 已正确定义
  • 初始化 (ArbInitializeArbiterInstance): 已完成,含内存分配、错误回滚、默认回调设置

调用方现状

调用方 文件 当前状态
Root IRQ Arbiter ntoskrnl/io/pnpmgr/arb/arbirq.c 回调函数全部 UNIMPLEMENTED
Root Memory Arbiter ntoskrnl/io/pnpmgr/arb/arbmem.c 回调函数全部 UNIMPLEMENTED
Root Bus Number Arbiter ntoskrnl/io/pnpmgr/arb/arbbus.c 回调函数全部 UNIMPLEMENTED
PCI I/O Arbiter drivers/bus/pcix/arb/ar_memio.c ario_Initializer/armem_Initializer 为 UNIMPLEMENTED
PCI Bus Number Arbiter drivers/bus/pcix/arb/ar_busno.c arbusno_Initializer 为 UNIMPLEMENTED
PCI Common Arbiter drivers/bus/pcix/arb/arb_comn.c PciInitializeArbiterRanges 为 UNIMPLEMENTED
I/O Resource Manager ntoskrnl/io/iomgr/iorsrce.c IoReportResourceUsage / IopLegacyResourceAllocation 为 halfplemented
PnP Resource Manager ntoskrnl/io/pnpmgr/pnpres.c IopFixupResourceListWithRequirements 存在但不使用仲裁器

关键依赖关系

复制代码
IoAssignResources
  → IopLegacyResourceAllocation (iorsrce.c, halfplemented)
      → IopFixupResourceListWithRequirements (pnpres.c, 简单匹配)
      → [未来] 应调用 ArbTestAllocation / ArbCommitAllocation

IopArbIrqInitialize / IopArbMemInitialize / IopArbBusNumberInitialize
  → ArbInitializeArbiterInstance (arbiter.c, 已实现)
  → 提供 UnpackRequirement / PackResource / UnpackResource / ScoreRequirement 回调

PnP 设备资源分配流程 (pnpres.c):
  HalAdjustResourceList → IopFixupResourceListWithRequirements
  → IopDetectResourceConflict → [未来] 应使用仲裁器检测冲突

Windows ARBITER_ACTION 参考

复制代码
ArbiterActionTestAllocation       - 测试分配是否可行
ArbiterActionRetestAllocation     - 重新测试分配
ArbiterActionCommitAllocation     - 提交/生效分配
ArbiterActionRollbackAllocation   - 回滚分配
ArbiterActionQueryAllocatedResources - 查询已分配资源
ArbiterActionWriteReservedResources  - 写入保留资源
ArbiterActionQueryConflict        - 查询冲突
ArbiterActionQueryArbitrate       - 查询仲裁结果
ArbiterActionAddReserved          - 添加保留资源
ArbiterActionBootAllocation       - 启动时分配

实施计划(共 7 个阶段)

阶段 1: 排序列表管理 (Ordering List Management)

目标: 实现排序列表的创建、释放、添加、裁剪和构建功能。

涉及文件

1.1 `sdk/lib/drivers/arbiter/arbiter.c`(file:///d:/reactos/sdk/lib/drivers/arbiter/arbiter.c)

函数 行号 当前 目标
ArbInitializeOrderingList 244 UNIMPLEMENTED 实现
ArbFreeOrderingList 256 UNIMPLEMENTED 实现
ArbAddOrdering 216 UNIMPLEMENTED 实现
ArbPruneOrdering 230 UNIMPLEMENTED 实现
ArbBuildAssignmentOrdering 267 UNIMPLEMENTED 实现

实现细节:

  • ArbInitializeOrderingList : 初始化 ARBITER_ORDERING_LIST 结构的 CountMaximum 字段,为 Orderings 数组分配初始内存(如 16 个条目)。如果 Maximum 已非零表示调用方已预分配,则直接重置 Count = 0

  • ArbFreeOrderingList : 如果 Orderings 非 NULL 且 Maximum > 0(表示由库分配),调用 ExFreePoolWithTag 释放。重置所有字段为零。

  • ArbAddOrdering : 检查列表是否已满(Count >= Maximum),如果是则用 ExAllocatePoolWithTag 扩容(翻倍策略)。添加新排序条目(StartEnd),递增 Count

  • ArbPruneOrdering : 遍历排序列表,删除与 [MinimumAddress, MaximumAddress] 无交集的条目。对于部分重叠的条目,裁剪起始或结束地址。

  • ArbBuildAssignmentOrdering : 核心函数。先 ArbFreeOrderingList 清空,然后从总线设备对象获取可用资源范围(CM 资源描述符),通过 TranslateOrderingFunction 回调转换为 IO 资源描述符,再用 ArbAddOrdering 添加到排序列表。如果 ReservedOrderName 非空,也构建保留列表。

测试/验证: 构建 bootcd 验证不再出现 UNIMPLEMENTED 警告。


阶段 2: 核心分配算法 (Allocation Algorithm)

目标: 实现基于回溯 (backtracking) 的资源分配算法核心。

涉及文件

2.1 `sdk/lib/drivers/arbiter/arbiter.c`(file:///d:/reactos/sdk/lib/drivers/arbiter/arbiter.c)

函数 行号 当前 目标
ArbPreprocessEntry 89 空实现 完整实现
ArbAllocateEntry 101 UNIMPLEMENTED 完整实现
ArbGetNextAllocationRange 114 UNIMPLEMENTED 完整实现
ArbFindSuitableRange 127 UNIMPLEMENTED 完整实现
ArbAddAllocation 140 UNIMPLEMENTED 完整实现
ArbBacktrackAllocation 152 UNIMPLEMENTED 完整实现

实现细节:

2.1.1 ArbPreprocessEntry

  • ARBITER_LIST_ENTRY 中提取资源需求
  • 使用 UnpackRequirement 回调解析 IO_RESOURCE_DESCRIPTOR
  • 初始化 ARBITER_ALLOCATION_STATE 的字段:StartEndCurrentMinimumCurrentMaximum
  • 构建 Alternatives 数组(替代资源方案),计算 AlternativeCount
  • 按优先级排序替代方案

2.1.2 ArbGetNextAllocationRange

  • 实现为状态机迭代器
  • CurrentAlternative 开始,依次遍历所有替代方案
  • 对每个替代方案,结合 PossibleAllocation 范围列表,计算实际可分配的地址范围
  • 使用 RtlFindRange 在可用范围内查找未占用的区间
  • 返回 TRUE 找到下一个范围,FALSE 已无更多范围

2.1.3 ArbFindSuitableRange

  • ArbGetNextAllocationRange 返回的范围内,由高到低尝试
  • 使用 RtlIsRangeAvailable 检查是否与已分配资源冲突
  • 考虑对齐约束 (Alignment) 和长度 (Length),计算合适的起始地址
  • 使用 ROUND_DOWN 对齐逻辑(参考 RtlFindRange

2.1.4 ArbAddAllocation

  • 使用已确定的地址范围,调用 RtlAddRange 添加到 Allocation 列表
  • 标记分配的属性 (Attributes) 和所有者
  • 在分配栈 (AllocationStack) 上记录当前分配状态,用于回溯

2.1.5 ArbBacktrackAllocation

  • 从分配栈弹出上一次分配的记录
  • 调用 RtlDeleteRangeAllocation 列表中删除
  • 恢复 ARBITER_ALLOCATION_STATE 到回溯前的状态

2.1.6 ArbAllocateEntry

  • 这是分配算法的入口,实现完整的分配循环:
    1. 调用 ArbPreprocessEntry 初始化状态
    2. 循环:
      a. 调用 ArbGetNextAllocationRange 获取下一个可分配范围
      b. 调用 ArbFindSuitableRange 在范围内找合适区间
      c. 找到则 ArbAddAllocation,返回成功
      d. 未找到则 ArbBacktrackAllocation,尝试下一个替代方案
    3. 所有方案尝试失败,返回 STATUS_NO_MORE_ENTRIES

算法伪代码:

复制代码
ArbAllocateEntry(Arbiter, ArbState):
    Status = ArbPreprocessEntry(Arbiter, ArbState)
    if FAILED(Status): return Status
    
    while TRUE:
        HasRange = ArbGetNextAllocationRange(Arbiter, ArbState)
        if !HasRange:
            // No more ranges for current alternative
            CouldBacktrack = ArbBacktrackAllocation(Arbiter, ArbState)
            if !CouldBacktrack:
                return STATUS_NO_MORE_ENTRIES
            continue
        
        Found = ArbFindSuitableRange(Arbiter, ArbState)
        if Found:
            ArbAddAllocation(Arbiter, ArbState)
            return STATUS_SUCCESS
        // Continue to next range

阶段 3: 事务管理 (Transaction Management)

目标: 实现资源分配的完整事务生命周期。

涉及文件

3.1 `sdk/lib/drivers/arbiter/arbiter.c`(file:///d:/reactos/sdk/lib/drivers/arbiter/arbiter.c)

函数 行号 当前 目标
ArbTestAllocation 26 UNIMPLEMENTED 完整实现
ArbRetestAllocation 39 UNIMPLEMENTED 完整实现
ArbCommitAllocation 52 UNIMPLEMENTED 完整实现
ArbRollbackAllocation 64 UNIMPLEMENTED 完整实现

实现细节:

3.1.1 ArbTestAllocation

  • 加锁:KeWaitForSingleObject(Arbiter->MutexEvent, ...)
  • 复制 Allocation 到临时范围列表(模拟分配的基础状态)
  • 遍历 ArbitrationList 中的每个 ARBITER_LIST_ENTRY
    • 对每个条目调用 ArbAllocateEntry 尝试分配
    • 如果分配失败,回滚所有已分配条目,返回 STATUS_CONFLICTING_ADDRESSES
  • 所有条目分配成功,记录但不提交
  • 解锁
  • 返回 STATUS_SUCCESS

3.1.2 ArbRetestAllocation

  • ArbTestAllocation 类似,但不清除之前的测试结果
  • 在已有测试分配的基础上,追加测试新的条目
  • 用于分步验证资源分配

3.1.3 ArbCommitAllocation

  • 加锁
  • ArbitrationList 中的分配结果写入仲裁器的正式 Allocation 列表
  • PossibleAllocation 中移除已分配的范围(使用 RtlDeleteRange
  • 设置 TransactionInProgress = TRUE
  • 同步分配结果到硬件(调用 PackResource 回调更新设备资源配置)
  • 解锁
  • 返回 STATUS_SUCCESS

3.1.4 ArbRollbackAllocation

  • 加锁
  • 清理临时分配状态
  • Allocation 中移除测试分配添加的条目
  • 使用分配栈逐层回溯
  • 设置 TransactionInProgress = FALSE
  • 解锁

阶段 4: 启动分配与冲突处理 (Boot & Conflict)

目标: 实现系统启动时的资源分配和冲突检测/处理功能。

涉及文件

4.1 `sdk/lib/drivers/arbiter/arbiter.c`(file:///d:/reactos/sdk/lib/drivers/arbiter/arbiter.c)

函数 行号 当前 目标
ArbBootAllocation 177 UNIMPLEMENTED 完整实现
ArbQueryConflict 191 UNIMPLEMENTED 完整实现
ArbOverrideConflict 165 UNIMPLEMENTED 完整实现
ArbAddReserved 77 UNIMPLEMENTED 完整实现
ArbStartArbiter 204 UNIMPLEMENTED 完整实现

实现细节:

4.1.1 ArbBootAllocation

  • 接收引导时 BIOS/固件已分配的资源列表
  • 遍历 ArbitrationList,对每个条目:
    • 检查是否已存在于引导资源配置中
    • 通过 ScoreRequirement 回调评分
    • 调用 ArbAllocateEntry 尝试分配
    • 如果失败,记录冲突但继续
  • 将引导分配标记为 ARBITER_FLAG_BOOT_CONFIG

4.1.2 ArbQueryConflict

  • 给定 ConflictingResource(一个 IO 资源描述符)
  • Allocation 列表中搜索重叠范围
  • 使用 RtlIsRangeAvailable 快速判断
  • 返回冲突设备列表(ARBITER_CONFLICT_INFO 数组)

4.1.3 ArbOverrideConflict

  • 强制分配指定的资源范围
  • 使用 RtlAddRange 添加到 Allocation 列表(即使有冲突)
  • 记录覆盖标记

4.1.4 ArbAddReserved

  • ReservedList 中添加保留资源
  • 这些资源不会通过正常分配流程分配给其他设备

4.1.5 ArbStartArbiter

  • 验证仲裁器状态完整性
  • 检查 AllocationPossibleAllocation 列表是否已初始化
  • 如果尚未有启动分配,调用 ArbBootAllocation

阶段 5: 更新 PnP 根仲裁器回调

目标: 为三个根仲裁器实现具体类型的 Unpack/Pack/Score 回调。

涉及文件

5.1 `ntoskrnl/io/pnpmgr/arb/arbirq.c`(file:///d:/reactos/ntoskrnl/io/pnpmgr/arb/arbirq.c)

函数 当前 目标
IopArbIrqUnpackRequirements UNIMPLEMENTED 实现解析 IRQ 需求
IopArbIrqPackResource UNIMPLEMENTED 实现打包 IRQ 资源
IopArbIrqUnpackResource UNIMPLEMENTED 实现解包 IRQ 资源
IopArbIrqScoreRequirement UNIMPLEMENTED 实现 IRQ 评分

实现细节:

  • IopArbIrqUnpackRequirements : 解析 IO_RESOURCE_DESCRIPTOR 中的 u.Interrupt 联合体,提取 MinimumVectorMaximumVector 作为地址范围,Length = 1(单个 IRQ),Alignment = 1
  • IopArbIrqPackResource : 将分配的起始地址填入 CM_PARTIAL_RESOURCE_DESCRIPTORu.Interrupt.Vector 字段
  • IopArbIrqUnpackResource : 从 CM_PARTIAL_RESOURCE_DESCRIPTOR 读取 u.Interrupt.Vector,设置 Start = Vector, Length = 1
  • IopArbIrqScoreRequirement: 根据 IRQ 优先级、是否共享等属性评分

5.2 `ntoskrnl/io/pnpmgr/arb/arbmem.c`(file:///d:/reactos/ntoskrnl/io/pnpmgr/arb/arbmem.c)

函数 当前 目标
IopArbMemUnpackRequirements UNIMPLEMENTED 实现解析内存需求
IopArbMemPackResource UNIMPLEMENTED 实现打包内存资源
IopArbMemUnpackResource UNIMPLEMENTED 实现解包内存资源
IopArbMemScoreRequirement UNIMPLEMENTED 实现内存评分
  • IopArbMemUnpackRequirements : 解析 u.MemoryStartLengthAlignment
  • IopArbMemPackResource : 填充 u.Memory.Startu.Memory.Length
  • IopArbMemUnpackResource: 解包内存地址和长度
  • IopArbIrqScoreRequirement: 内存范围评分(优先使用低地址等)

5.3 `ntoskrnl/io/pnpmgr/arb/arbbus.c`(file:///d:/reactos/ntoskrnl/io/pnpmgr/arb/arbbus.c)

函数 当前 目标
IopArbBusNumberUnpackRequirements UNIMPLEMENTED 实现解析总线号需求
IopArbBusNumberPackResource UNIMPLEMENTED 实现打包总线号资源
IopArbBusNumberUnpackResource UNIMPLEMENTED 实现解包总线号
IopArbBusNumberScoreRequirement UNIMPLEMENTED 实现总线号评分
  • 总线号是标量资源,Length = 1,范围由 MinimumAddress ~ MaximumAddress 表示

注意 : 这三个文件中的 Initialize 函数调用 ArbInitializeArbiterInstance 时,

当前传递了错误的资源类型参数(CmResourceTypeBusNumber 硬编码)。需要修正:

  • IopArbIrqInitializeCmResourceTypeInterrupt
  • IopArbMemInitializeCmResourceTypeMemory
  • IopArbBusNumberInitializeCmResourceTypeBusNumber(正确,无需修改)

阶段 6: 更新 PCI 总线仲裁器

目标: 使 PCI 总线驱动能够使用仲裁器库进行 PCI 桥资源分配。

涉及文件

6.1 `drivers/bus/pcix/arb/arb_comn.c`(file:///d:/reactos/drivers/bus/pcix/arb/arb_comn.c)

当前 目标
L191 // Arb library isn't yet implemented 使用 ArbInitializeArbiterInstance 初始化 PCI 仲裁器
L131-206 PciInitializeArbiterRanges 为 UNIMPLEMENTED 实现 PCI 桥资源范围初始化
  • PciInitializeArbiterRanges 中,遍历 I/O 和 Memory 仲裁器
  • 使用 ArbInitializeArbiterInstance 初始化每个仲裁器实例
  • 设置正确的 UnpackRequirementPackResourceUnpackResourceScoreRequirement 回调

6.2 `drivers/bus/pcix/arb/ar_memio.c`(file:///d:/reactos/drivers/bus/pcix/arb/ar_memio.c)

函数 当前 目标
ario_Initializer UNIMPLEMENTED 实现 I/O 端口仲裁器初始化
armem_Initializer UNIMPLEMENTED 实现内存仲裁器初始化
ario_ApplyBrokenVideoHack UNIMPLEMENTED 修复损坏视频 BIOS 的 VGA 范围
  • 为 PCI I/O 和 Memory 创建具体的 Unpack、Pack、Unpack、Score 回调函数
  • ario_ApplyBrokenVideoHack 中:释放 VGA 兼容范围的预留,重构建排序

6.3 `drivers/bus/pcix/arb/ar_busno.c`(file:///d:/reactos/drivers/bus/pcix/arb/ar_busno.c)

当前 目标
L48 UNIMPLEMENTED 取消注释回调注册代码
L54-55 #if 0 包裹的回调注册 启用 arbusno_UnpackRequirement 等回调
  • 取消第 50-55 行的 #if 0 注释块
  • 实现 arbusno_UnpackRequirementarbusno_PackResourcearbusno_UnpackResourcearbusno_ScoreRequirement
  • 按 PCI 桥规范分配总线号

阶段 7: 集成 I/O 资源管理器与 PnP 管理器

目标: 使上层资源管理 API 使用仲裁器进行实际的资源分配和冲突检测。

涉及文件

7.1 `ntoskrnl/io/iomgr/iorsrce.c`(file:///d:/reactos/ntoskrnl/io/iomgr/iorsrce.c)

函数 当前 目标
IoReportResourceUsage halfplemented 使用仲裁器检测冲突
IopLegacyResourceAllocation halfplemented 使用仲裁器分配资源
  • IoReportResourceUsage : 将当前资源列表注册到对应类型的仲裁器中,使用 ArbTestAllocation / ArbCommitAllocation
  • IopLegacyResourceAllocation : 构建 ARBITER_LIST_ENTRY 列表,调用仲裁器进行分配

7.2 `ntoskrnl/io/pnpmgr/pnpres.c`(file:///d:/reactos/ntoskrnl/io/pnpmgr/pnpres.c)

函数 当前 目标
IopFixupResourceListWithRequirements 简单匹配 可选:使用仲裁器验证结果
IopDetectResourceConflict 简单冲突检测 可选:使用仲裁器查询冲突
  • IopFixupResourceListWithRequirements: 当前通过遍历和简单匹配实现,可保持
  • IopDetectResourceConflict : 当前通过直接地址比较实现,可保持或使用 ArbQueryConflict

实施顺序与依赖关系

复制代码
阶段 1 (排序列表)
    ↓
阶段 2 (分配算法) ← 依赖于阶段 1(需要排序)
    ↓
阶段 3 (事务管理) ← 依赖于阶段 2(需要分配算法)
    ↓
阶段 4 (启动/冲突) ← 依赖于阶段 3(需要事务机制)
    ↓
阶段 5 (PnP 回调) ← 依赖于阶段 1-4(需要完整的仲裁器库)
    ↓
阶段 6 (PCI 回调) ← 依赖于阶段 1-4(需要完整的仲裁器库)
    ↓
阶段 7 (上层集成) ← 依赖于阶段 1-5(需要完整的仲裁器和根仲裁器)

每个阶段有独立的代码交付物,可以逐个阶段交付和测试。


验证方案

  1. 编译验证 : 每个阶段完成后运行 ninja 确保无编译错误
  2. UNIMPLEMENTED 警告检查 : 运行 ninja 检查 DPRINT 输出,确保不再有 arbiter 相关警告
  3. 启动测试 : 在 QEMU 中运行 bootcd.iso,验证 PnP 设备枚举和资源分配
  4. 回归测试: 确保现有功能不受影响

已知决策与假设

  1. 分配算法选择: 采用基于回溯的贪心分配(先到先服务 + 替代方案回退),与 Windows 行为一致
  2. 同步模型 : 使用 KEVENT 互斥事件保护仲裁器状态,PASSIVE_LEVEL 执行
  3. 内存管理 : 使用 PagedPool 分配(所有函数在 PAGE 段),非分页池仅用于互斥事件
  4. 排序策略: 地址从高到低分配(与 Windows 默认行为一致),以减少碎片
  5. 范围列表操作: 全部基于已实现的 RTL Range List 函数,不引入新的数据结构# ReactOS 硬件资源仲裁器 (Arbiter) 完整实现计划

概述

本计划目标是以增量方式完整实现 sdk/lib/drivers/arbiter/arbiter.c 的全部 21 个函数,并更新所有调用方以正确使用仲裁器功能。当前该库仅有 ArbInitializeArbiterInstance 完成实现,其余 20 个函数均为 UNIMPLEMENTED 存根。


当前状态分析

已实现的基础设施

  • RTL Range List (sdk/lib/rtl/rangelist.c): 完整可用,提供 RtlAddRangeRtlFindRangeRtlDeleteRangeRtlInvertRangeListRtlIsRangeAvailableRtlMergeRangeLists
  • 数据结构 (sdk/lib/drivers/arbiter/arbiter.h): ARBITER_INSTANCEARBITER_ALLOCATION_STATEARBITER_ORDERING_LISTARBITER_ALTERNATIVE 已正确定义
  • 初始化 (ArbInitializeArbiterInstance): 已完成,含内存分配、错误回滚、默认回调设置

调用方现状

调用方 文件 当前状态
Root IRQ Arbiter ntoskrnl/io/pnpmgr/arb/arbirq.c 回调函数全部 UNIMPLEMENTED
Root Memory Arbiter ntoskrnl/io/pnpmgr/arb/arbmem.c 回调函数全部 UNIMPLEMENTED
Root Bus Number Arbiter ntoskrnl/io/pnpmgr/arb/arbbus.c 回调函数全部 UNIMPLEMENTED
PCI I/O Arbiter drivers/bus/pcix/arb/ar_memio.c ario_Initializer/armem_Initializer 为 UNIMPLEMENTED
PCI Bus Number Arbiter drivers/bus/pcix/arb/ar_busno.c arbusno_Initializer 为 UNIMPLEMENTED
PCI Common Arbiter drivers/bus/pcix/arb/arb_comn.c PciInitializeArbiterRanges 为 UNIMPLEMENTED
I/O Resource Manager ntoskrnl/io/iomgr/iorsrce.c IoReportResourceUsage / IopLegacyResourceAllocation 为 halfplemented
PnP Resource Manager ntoskrnl/io/pnpmgr/pnpres.c IopFixupResourceListWithRequirements 存在但不使用仲裁器

关键依赖关系

复制代码
IoAssignResources
  → IopLegacyResourceAllocation (iorsrce.c, halfplemented)
      → IopFixupResourceListWithRequirements (pnpres.c, 简单匹配)
      → [未来] 应调用 ArbTestAllocation / ArbCommitAllocation

IopArbIrqInitialize / IopArbMemInitialize / IopArbBusNumberInitialize
  → ArbInitializeArbiterInstance (arbiter.c, 已实现)
  → 提供 UnpackRequirement / PackResource / UnpackResource / ScoreRequirement 回调

PnP 设备资源分配流程 (pnpres.c):
  HalAdjustResourceList → IopFixupResourceListWithRequirements
  → IopDetectResourceConflict → [未来] 应使用仲裁器检测冲突

Windows ARBITER_ACTION 参考

复制代码
ArbiterActionTestAllocation       - 测试分配是否可行
ArbiterActionRetestAllocation     - 重新测试分配
ArbiterActionCommitAllocation     - 提交/生效分配
ArbiterActionRollbackAllocation   - 回滚分配
ArbiterActionQueryAllocatedResources - 查询已分配资源
ArbiterActionWriteReservedResources  - 写入保留资源
ArbiterActionQueryConflict        - 查询冲突
ArbiterActionQueryArbitrate       - 查询仲裁结果
ArbiterActionAddReserved          - 添加保留资源
ArbiterActionBootAllocation       - 启动时分配

实施计划(共 7 个阶段)

阶段 1: 排序列表管理 (Ordering List Management)

目标: 实现排序列表的创建、释放、添加、裁剪和构建功能。

涉及文件

1.1 `sdk/lib/drivers/arbiter/arbiter.c`(file:///d:/reactos/sdk/lib/drivers/arbiter/arbiter.c)

函数 行号 当前 目标
ArbInitializeOrderingList 244 UNIMPLEMENTED 实现
ArbFreeOrderingList 256 UNIMPLEMENTED 实现
ArbAddOrdering 216 UNIMPLEMENTED 实现
ArbPruneOrdering 230 UNIMPLEMENTED 实现
ArbBuildAssignmentOrdering 267 UNIMPLEMENTED 实现

实现细节:

  • ArbInitializeOrderingList : 初始化 ARBITER_ORDERING_LIST 结构的 CountMaximum 字段,为 Orderings 数组分配初始内存(如 16 个条目)。如果 Maximum 已非零表示调用方已预分配,则直接重置 Count = 0

  • ArbFreeOrderingList : 如果 Orderings 非 NULL 且 Maximum > 0(表示由库分配),调用 ExFreePoolWithTag 释放。重置所有字段为零。

  • ArbAddOrdering : 检查列表是否已满(Count >= Maximum),如果是则用 ExAllocatePoolWithTag 扩容(翻倍策略)。添加新排序条目(StartEnd),递增 Count

  • ArbPruneOrdering : 遍历排序列表,删除与 [MinimumAddress, MaximumAddress] 无交集的条目。对于部分重叠的条目,裁剪起始或结束地址。

  • ArbBuildAssignmentOrdering : 核心函数。先 ArbFreeOrderingList 清空,然后从总线设备对象获取可用资源范围(CM 资源描述符),通过 TranslateOrderingFunction 回调转换为 IO 资源描述符,再用 ArbAddOrdering 添加到排序列表。如果 ReservedOrderName 非空,也构建保留列表。

测试/验证: 构建 bootcd 验证不再出现 UNIMPLEMENTED 警告。


阶段 2: 核心分配算法 (Allocation Algorithm)

目标: 实现基于回溯 (backtracking) 的资源分配算法核心。

涉及文件

2.1 `sdk/lib/drivers/arbiter/arbiter.c`(file:///d:/reactos/sdk/lib/drivers/arbiter/arbiter.c)

函数 行号 当前 目标
ArbPreprocessEntry 89 空实现 完整实现
ArbAllocateEntry 101 UNIMPLEMENTED 完整实现
ArbGetNextAllocationRange 114 UNIMPLEMENTED 完整实现
ArbFindSuitableRange 127 UNIMPLEMENTED 完整实现
ArbAddAllocation 140 UNIMPLEMENTED 完整实现
ArbBacktrackAllocation 152 UNIMPLEMENTED 完整实现

实现细节:

2.1.1 ArbPreprocessEntry

  • ARBITER_LIST_ENTRY 中提取资源需求
  • 使用 UnpackRequirement 回调解析 IO_RESOURCE_DESCRIPTOR
  • 初始化 ARBITER_ALLOCATION_STATE 的字段:StartEndCurrentMinimumCurrentMaximum
  • 构建 Alternatives 数组(替代资源方案),计算 AlternativeCount
  • 按优先级排序替代方案

2.1.2 ArbGetNextAllocationRange

  • 实现为状态机迭代器
  • CurrentAlternative 开始,依次遍历所有替代方案
  • 对每个替代方案,结合 PossibleAllocation 范围列表,计算实际可分配的地址范围
  • 使用 RtlFindRange 在可用范围内查找未占用的区间
  • 返回 TRUE 找到下一个范围,FALSE 已无更多范围

2.1.3 ArbFindSuitableRange

  • ArbGetNextAllocationRange 返回的范围内,由高到低尝试
  • 使用 RtlIsRangeAvailable 检查是否与已分配资源冲突
  • 考虑对齐约束 (Alignment) 和长度 (Length),计算合适的起始地址
  • 使用 ROUND_DOWN 对齐逻辑(参考 RtlFindRange

2.1.4 ArbAddAllocation

  • 使用已确定的地址范围,调用 RtlAddRange 添加到 Allocation 列表
  • 标记分配的属性 (Attributes) 和所有者
  • 在分配栈 (AllocationStack) 上记录当前分配状态,用于回溯

2.1.5 ArbBacktrackAllocation

  • 从分配栈弹出上一次分配的记录
  • 调用 RtlDeleteRangeAllocation 列表中删除
  • 恢复 ARBITER_ALLOCATION_STATE 到回溯前的状态

2.1.6 ArbAllocateEntry

  • 这是分配算法的入口,实现完整的分配循环:
    1. 调用 ArbPreprocessEntry 初始化状态
    2. 循环:
      a. 调用 ArbGetNextAllocationRange 获取下一个可分配范围
      b. 调用 ArbFindSuitableRange 在范围内找合适区间
      c. 找到则 ArbAddAllocation,返回成功
      d. 未找到则 ArbBacktrackAllocation,尝试下一个替代方案
    3. 所有方案尝试失败,返回 STATUS_NO_MORE_ENTRIES

算法伪代码:

复制代码
ArbAllocateEntry(Arbiter, ArbState):
    Status = ArbPreprocessEntry(Arbiter, ArbState)
    if FAILED(Status): return Status
    
    while TRUE:
        HasRange = ArbGetNextAllocationRange(Arbiter, ArbState)
        if !HasRange:
            // No more ranges for current alternative
            CouldBacktrack = ArbBacktrackAllocation(Arbiter, ArbState)
            if !CouldBacktrack:
                return STATUS_NO_MORE_ENTRIES
            continue
        
        Found = ArbFindSuitableRange(Arbiter, ArbState)
        if Found:
            ArbAddAllocation(Arbiter, ArbState)
            return STATUS_SUCCESS
        // Continue to next range

阶段 3: 事务管理 (Transaction Management)

目标: 实现资源分配的完整事务生命周期。

涉及文件

3.1 `sdk/lib/drivers/arbiter/arbiter.c`(file:///d:/reactos/sdk/lib/drivers/arbiter/arbiter.c)

函数 行号 当前 目标
ArbTestAllocation 26 UNIMPLEMENTED 完整实现
ArbRetestAllocation 39 UNIMPLEMENTED 完整实现
ArbCommitAllocation 52 UNIMPLEMENTED 完整实现
ArbRollbackAllocation 64 UNIMPLEMENTED 完整实现

实现细节:

3.1.1 ArbTestAllocation

  • 加锁:KeWaitForSingleObject(Arbiter->MutexEvent, ...)
  • 复制 Allocation 到临时范围列表(模拟分配的基础状态)
  • 遍历 ArbitrationList 中的每个 ARBITER_LIST_ENTRY
    • 对每个条目调用 ArbAllocateEntry 尝试分配
    • 如果分配失败,回滚所有已分配条目,返回 STATUS_CONFLICTING_ADDRESSES
  • 所有条目分配成功,记录但不提交
  • 解锁
  • 返回 STATUS_SUCCESS

3.1.2 ArbRetestAllocation

  • ArbTestAllocation 类似,但不清除之前的测试结果
  • 在已有测试分配的基础上,追加测试新的条目
  • 用于分步验证资源分配

3.1.3 ArbCommitAllocation

  • 加锁
  • ArbitrationList 中的分配结果写入仲裁器的正式 Allocation 列表
  • PossibleAllocation 中移除已分配的范围(使用 RtlDeleteRange
  • 设置 TransactionInProgress = TRUE
  • 同步分配结果到硬件(调用 PackResource 回调更新设备资源配置)
  • 解锁
  • 返回 STATUS_SUCCESS

3.1.4 ArbRollbackAllocation

  • 加锁
  • 清理临时分配状态
  • Allocation 中移除测试分配添加的条目
  • 使用分配栈逐层回溯
  • 设置 TransactionInProgress = FALSE
  • 解锁

阶段 4: 启动分配与冲突处理 (Boot & Conflict)

目标: 实现系统启动时的资源分配和冲突检测/处理功能。

涉及文件

4.1 `sdk/lib/drivers/arbiter/arbiter.c`(file:///d:/reactos/sdk/lib/drivers/arbiter/arbiter.c)

函数 行号 当前 目标
ArbBootAllocation 177 UNIMPLEMENTED 完整实现
ArbQueryConflict 191 UNIMPLEMENTED 完整实现
ArbOverrideConflict 165 UNIMPLEMENTED 完整实现
ArbAddReserved 77 UNIMPLEMENTED 完整实现
ArbStartArbiter 204 UNIMPLEMENTED 完整实现

实现细节:

4.1.1 ArbBootAllocation

  • 接收引导时 BIOS/固件已分配的资源列表
  • 遍历 ArbitrationList,对每个条目:
    • 检查是否已存在于引导资源配置中
    • 通过 ScoreRequirement 回调评分
    • 调用 ArbAllocateEntry 尝试分配
    • 如果失败,记录冲突但继续
  • 将引导分配标记为 ARBITER_FLAG_BOOT_CONFIG

4.1.2 ArbQueryConflict

  • 给定 ConflictingResource(一个 IO 资源描述符)
  • Allocation 列表中搜索重叠范围
  • 使用 RtlIsRangeAvailable 快速判断
  • 返回冲突设备列表(ARBITER_CONFLICT_INFO 数组)

4.1.3 ArbOverrideConflict

  • 强制分配指定的资源范围
  • 使用 RtlAddRange 添加到 Allocation 列表(即使有冲突)
  • 记录覆盖标记

4.1.4 ArbAddReserved

  • ReservedList 中添加保留资源
  • 这些资源不会通过正常分配流程分配给其他设备

4.1.5 ArbStartArbiter

  • 验证仲裁器状态完整性
  • 检查 AllocationPossibleAllocation 列表是否已初始化
  • 如果尚未有启动分配,调用 ArbBootAllocation

阶段 5: 更新 PnP 根仲裁器回调

目标: 为三个根仲裁器实现具体类型的 Unpack/Pack/Score 回调。

涉及文件

5.1 `ntoskrnl/io/pnpmgr/arb/arbirq.c`(file:///d:/reactos/ntoskrnl/io/pnpmgr/arb/arbirq.c)

函数 当前 目标
IopArbIrqUnpackRequirements UNIMPLEMENTED 实现解析 IRQ 需求
IopArbIrqPackResource UNIMPLEMENTED 实现打包 IRQ 资源
IopArbIrqUnpackResource UNIMPLEMENTED 实现解包 IRQ 资源
IopArbIrqScoreRequirement UNIMPLEMENTED 实现 IRQ 评分

实现细节:

  • IopArbIrqUnpackRequirements : 解析 IO_RESOURCE_DESCRIPTOR 中的 u.Interrupt 联合体,提取 MinimumVectorMaximumVector 作为地址范围,Length = 1(单个 IRQ),Alignment = 1
  • IopArbIrqPackResource : 将分配的起始地址填入 CM_PARTIAL_RESOURCE_DESCRIPTORu.Interrupt.Vector 字段
  • IopArbIrqUnpackResource : 从 CM_PARTIAL_RESOURCE_DESCRIPTOR 读取 u.Interrupt.Vector,设置 Start = Vector, Length = 1
  • IopArbIrqScoreRequirement: 根据 IRQ 优先级、是否共享等属性评分

5.2 `ntoskrnl/io/pnpmgr/arb/arbmem.c`(file:///d:/reactos/ntoskrnl/io/pnpmgr/arb/arbmem.c)

函数 当前 目标
IopArbMemUnpackRequirements UNIMPLEMENTED 实现解析内存需求
IopArbMemPackResource UNIMPLEMENTED 实现打包内存资源
IopArbMemUnpackResource UNIMPLEMENTED 实现解包内存资源
IopArbMemScoreRequirement UNIMPLEMENTED 实现内存评分
  • IopArbMemUnpackRequirements : 解析 u.MemoryStartLengthAlignment
  • IopArbMemPackResource : 填充 u.Memory.Startu.Memory.Length
  • IopArbMemUnpackResource: 解包内存地址和长度
  • IopArbIrqScoreRequirement: 内存范围评分(优先使用低地址等)

5.3 `ntoskrnl/io/pnpmgr/arb/arbbus.c`(file:///d:/reactos/ntoskrnl/io/pnpmgr/arb/arbbus.c)

函数 当前 目标
IopArbBusNumberUnpackRequirements UNIMPLEMENTED 实现解析总线号需求
IopArbBusNumberPackResource UNIMPLEMENTED 实现打包总线号资源
IopArbBusNumberUnpackResource UNIMPLEMENTED 实现解包总线号
IopArbBusNumberScoreRequirement UNIMPLEMENTED 实现总线号评分
  • 总线号是标量资源,Length = 1,范围由 MinimumAddress ~ MaximumAddress 表示

注意 : 这三个文件中的 Initialize 函数调用 ArbInitializeArbiterInstance 时,

当前传递了错误的资源类型参数(CmResourceTypeBusNumber 硬编码)。需要修正:

  • IopArbIrqInitializeCmResourceTypeInterrupt
  • IopArbMemInitializeCmResourceTypeMemory
  • IopArbBusNumberInitializeCmResourceTypeBusNumber(正确,无需修改)

阶段 6: 更新 PCI 总线仲裁器

目标: 使 PCI 总线驱动能够使用仲裁器库进行 PCI 桥资源分配。

涉及文件

6.1 `drivers/bus/pcix/arb/arb_comn.c`(file:///d:/reactos/drivers/bus/pcix/arb/arb_comn.c)

当前 目标
L191 // Arb library isn't yet implemented 使用 ArbInitializeArbiterInstance 初始化 PCI 仲裁器
L131-206 PciInitializeArbiterRanges 为 UNIMPLEMENTED 实现 PCI 桥资源范围初始化
  • PciInitializeArbiterRanges 中,遍历 I/O 和 Memory 仲裁器
  • 使用 ArbInitializeArbiterInstance 初始化每个仲裁器实例
  • 设置正确的 UnpackRequirementPackResourceUnpackResourceScoreRequirement 回调

6.2 `drivers/bus/pcix/arb/ar_memio.c`(file:///d:/reactos/drivers/bus/pcix/arb/ar_memio.c)

函数 当前 目标
ario_Initializer UNIMPLEMENTED 实现 I/O 端口仲裁器初始化
armem_Initializer UNIMPLEMENTED 实现内存仲裁器初始化
ario_ApplyBrokenVideoHack UNIMPLEMENTED 修复损坏视频 BIOS 的 VGA 范围
  • 为 PCI I/O 和 Memory 创建具体的 Unpack、Pack、Unpack、Score 回调函数
  • ario_ApplyBrokenVideoHack 中:释放 VGA 兼容范围的预留,重构建排序

6.3 `drivers/bus/pcix/arb/ar_busno.c`(file:///d:/reactos/drivers/bus/pcix/arb/ar_busno.c)

当前 目标
L48 UNIMPLEMENTED 取消注释回调注册代码
L54-55 #if 0 包裹的回调注册 启用 arbusno_UnpackRequirement 等回调
  • 取消第 50-55 行的 #if 0 注释块
  • 实现 arbusno_UnpackRequirementarbusno_PackResourcearbusno_UnpackResourcearbusno_ScoreRequirement
  • 按 PCI 桥规范分配总线号

阶段 7: 集成 I/O 资源管理器与 PnP 管理器

目标: 使上层资源管理 API 使用仲裁器进行实际的资源分配和冲突检测。

涉及文件

7.1 `ntoskrnl/io/iomgr/iorsrce.c`(file:///d:/reactos/ntoskrnl/io/iomgr/iorsrce.c)

函数 当前 目标
IoReportResourceUsage halfplemented 使用仲裁器检测冲突
IopLegacyResourceAllocation halfplemented 使用仲裁器分配资源
  • IoReportResourceUsage : 将当前资源列表注册到对应类型的仲裁器中,使用 ArbTestAllocation / ArbCommitAllocation
  • IopLegacyResourceAllocation : 构建 ARBITER_LIST_ENTRY 列表,调用仲裁器进行分配

7.2 `ntoskrnl/io/pnpmgr/pnpres.c`(file:///d:/reactos/ntoskrnl/io/pnpmgr/pnpres.c)

函数 当前 目标
IopFixupResourceListWithRequirements 简单匹配 可选:使用仲裁器验证结果
IopDetectResourceConflict 简单冲突检测 可选:使用仲裁器查询冲突
  • IopFixupResourceListWithRequirements: 当前通过遍历和简单匹配实现,可保持
  • IopDetectResourceConflict : 当前通过直接地址比较实现,可保持或使用 ArbQueryConflict

实施顺序与依赖关系

复制代码
阶段 1 (排序列表)
    ↓
阶段 2 (分配算法) ← 依赖于阶段 1(需要排序)
    ↓
阶段 3 (事务管理) ← 依赖于阶段 2(需要分配算法)
    ↓
阶段 4 (启动/冲突) ← 依赖于阶段 3(需要事务机制)
    ↓
阶段 5 (PnP 回调) ← 依赖于阶段 1-4(需要完整的仲裁器库)
    ↓
阶段 6 (PCI 回调) ← 依赖于阶段 1-4(需要完整的仲裁器库)
    ↓
阶段 7 (上层集成) ← 依赖于阶段 1-5(需要完整的仲裁器和根仲裁器)

每个阶段有独立的代码交付物,可以逐个阶段交付和测试。


验证方案

  1. 编译验证 : 每个阶段完成后运行 ninja 确保无编译错误
  2. UNIMPLEMENTED 警告检查 : 运行 ninja 检查 DPRINT 输出,确保不再有 arbiter 相关警告
  3. 启动测试 : 在 QEMU 中运行 bootcd.iso,验证 PnP 设备枚举和资源分配
  4. 回归测试: 确保现有功能不受影响

已知决策与假设

  1. 分配算法选择: 采用基于回溯的贪心分配(先到先服务 + 替代方案回退),与 Windows 行为一致
  2. 同步模型 : 使用 KEVENT 互斥事件保护仲裁器状态,PASSIVE_LEVEL 执行
  3. 内存管理 : 使用 PagedPool 分配(所有函数在 PAGE 段),非分页池仅用于互斥事件
  4. 排序策略: 地址从高到低分配(与 Windows 默认行为一致),以减少碎片
  5. 范围列表操作: 全部基于已实现的 RTL Range List 函数,不引入新的数据结构
  6. `/*

/* INCLUDES *******************************************************************/

#include <ntifs.h>

#include <ndk/rtlfuncs.h>

#include "arbiter.h"

#define NDEBUG

#include <debug.h>

/* GLOBALS ********************************************************************/

/* DATA **********************************************************************/

#define INITIAL_ORDERING_COUNT 16

/* FORWARD DECLARATIONS ******************************************************/

CODE_SEG("PAGE")

NTSTATUS

NTAPI

ArbAddOrdering(

Out PARBITER_ORDERING_LIST OrderList,

In UINT64 MinimumAddress,

In UINT64 MaximumAddress);

/* FUNCTIONS ******************************************************************/

CODE_SEG("PAGE")

NTSTATUS

NTAPI

ArbTestAllocation(

In PARBITER_INSTANCE Arbiter,

In PLIST_ENTRY ArbitrationList)

{

NTSTATUS Status;

PLIST_ENTRY Entry;

PARBITER_LIST_ENTRY ListEntry;

ARBITER_ALLOCATION_STATE ArbState;

RTL_RANGE_LIST SavedAllocation;

ULONG Count;

复制代码
PAGED_CODE();

/* Lock the arbiter */
if (Arbiter->MutexEvent)
    KeWaitForSingleObject(Arbiter->MutexEvent, Executive, KernelMode, FALSE, NULL);

/* Save the current allocation state for rollback */
RtlInitializeRangeList(&SavedAllocation);

if (Arbiter->Allocation)
{
    Status = RtlCopyRangeList(&SavedAllocation, Arbiter->Allocation);
    if (!NT_SUCCESS(Status))
    {
        if (Arbiter->MutexEvent)
            KeSetEvent(Arbiter->MutexEvent, 0, FALSE);
        return Status;
    }
}

/* Iterate through the arbitration list */
Count = 0;
Entry = ArbitrationList->Flink;
while (Entry != ArbitrationList)
{
    ListEntry = CONTAINING_RECORD(Entry, ARBITER_LIST_ENTRY, ListEntry);

    /* Initialize allocation state */
    RtlZeroMemory(&ArbState, sizeof(ARBITER_ALLOCATION_STATE));
    ArbState.Entry = ListEntry;

    /* Try to allocate for this entry */
    Status = ArbAllocateEntry(Arbiter, &ArbState);

    if (!NT_SUCCESS(Status))
    {
        /* Allocation failed - rollback everything */
        DPRINT1("ArbTestAllocation: Failed to allocate for entry %p, Status %x\n",
                ListEntry, Status);

        /* Restore the saved allocation */
        if (Arbiter->Allocation)
        {
            RtlFreeRangeList(Arbiter->Allocation);
            RtlCopyRangeList(Arbiter->Allocation, &SavedAllocation);
        }

        RtlFreeRangeList(&SavedAllocation);

        if (Arbiter->MutexEvent)
            KeSetEvent(Arbiter->MutexEvent, 0, FALSE);

        return STATUS_CONFLICTING_ADDRESSES;
    }

    Count++;
    Entry = Entry->Flink;
}

/* Test succeeded - restore saved state (don't commit yet) */
if (Arbiter->Allocation)
{
    RtlFreeRangeList(Arbiter->Allocation);
    RtlCopyRangeList(Arbiter->Allocation, &SavedAllocation);
}

RtlFreeRangeList(&SavedAllocation);

if (Arbiter->MutexEvent)
    KeSetEvent(Arbiter->MutexEvent, 0, FALSE);

return STATUS_SUCCESS;

}

CODE_SEG("PAGE")

NTSTATUS

NTAPI

ArbRetestAllocation(

In PARBITER_INSTANCE Arbiter,

In PLIST_ENTRY ArbitrationList)

{

NTSTATUS Status;

PLIST_ENTRY Entry;

PARBITER_LIST_ENTRY ListEntry;

ARBITER_ALLOCATION_STATE ArbState;

RTL_RANGE_LIST SavedAllocation;

复制代码
PAGED_CODE();

/* Lock the arbiter */
if (Arbiter->MutexEvent)
    KeWaitForSingleObject(Arbiter->MutexEvent, Executive, KernelMode, FALSE, NULL);

/* Save the current allocation state */
RtlInitializeRangeList(&SavedAllocation);

if (Arbiter->Allocation)
{
    Status = RtlCopyRangeList(&SavedAllocation, Arbiter->Allocation);
    if (!NT_SUCCESS(Status))
    {
        if (Arbiter->MutexEvent)
            KeSetEvent(Arbiter->MutexEvent, 0, FALSE);
        return Status;
    }
}

/* Iterate through the arbitration list - same as Test but
   without clearing previous test results */
Entry = ArbitrationList->Flink;
while (Entry != ArbitrationList)
{
    ListEntry = CONTAINING_RECORD(Entry, ARBITER_LIST_ENTRY, ListEntry);

    RtlZeroMemory(&ArbState, sizeof(ARBITER_ALLOCATION_STATE));
    ArbState.Entry = ListEntry;

    Status = ArbAllocateEntry(Arbiter, &ArbState);

    if (!NT_SUCCESS(Status))
    {
        DPRINT1("ArbRetestAllocation: Failed for entry %p, Status %x\n",
                ListEntry, Status);

        /* Restore saved state */
        if (Arbiter->Allocation)
        {
            RtlFreeRangeList(Arbiter->Allocation);
            RtlCopyRangeList(Arbiter->Allocation, &SavedAllocation);
        }

        RtlFreeRangeList(&SavedAllocation);

        if (Arbiter->MutexEvent)
            KeSetEvent(Arbiter->MutexEvent, 0, FALSE);

        return STATUS_CONFLICTING_ADDRESSES;
    }

    Entry = Entry->Flink;
}

/* Restore saved state (don't commit yet) */
if (Arbiter->Allocation)
{
    RtlFreeRangeList(Arbiter->Allocation);
    RtlCopyRangeList(Arbiter->Allocation, &SavedAllocation);
}

RtlFreeRangeList(&SavedAllocation);

if (Arbiter->MutexEvent)
    KeSetEvent(Arbiter->MutexEvent, 0, FALSE);

return STATUS_SUCCESS;

}

CODE_SEG("PAGE")

NTSTATUS

NTAPI

ArbCommitAllocation(

In PARBITER_INSTANCE Arbiter)

{

PAGED_CODE();

复制代码
/* Lock the arbiter */
if (Arbiter->MutexEvent)
    KeWaitForSingleObject(Arbiter->MutexEvent, Executive, KernelMode, FALSE, NULL);

/* Mark transaction as in progress */
Arbiter->TransactionInProgress = TRUE;

/* The allocation has already been applied to the Arbiter->Allocation
   list during ArbTestAllocation/ArbAllocateEntry. On commit, we
   just need to mark it as official. */

/* Update PossibleAllocation to reflect committed state */
if (Arbiter->PossibleAllocation)
{
    /* We already removed allocated ranges during ArbAddAllocation,
       so PossibleAllocation is already up to date. */
}

/* Notify the bus driver of the committed allocation via PackResource */
if (Arbiter->BusDeviceObject)
{
    /* In a full implementation, we would iterate through the
       allocated resources and call PackResource to update the
       device's resource configuration. */
}

if (Arbiter->MutexEvent)
    KeSetEvent(Arbiter->MutexEvent, 0, FALSE);

return STATUS_SUCCESS;

}

CODE_SEG("PAGE")

NTSTATUS

NTAPI

ArbRollbackAllocation(

In PARBITER_INSTANCE Arbiter)

{

PAGED_CODE();

复制代码
/* Lock the arbiter */
if (Arbiter->MutexEvent)
    KeWaitForSingleObject(Arbiter->MutexEvent, Executive, KernelMode, FALSE, NULL);

/* Clear the transaction flag */
Arbiter->TransactionInProgress = FALSE;

/* Re-initialize the allocation list (clearing any test allocations) */
if (Arbiter->Allocation)
{
    /* Free existing list and create a fresh empty one */
    RtlFreeRangeList(Arbiter->Allocation);
    RtlInitializeRangeList(Arbiter->Allocation);
}

/* Restore PossibleAllocation to match the ordering list reset */
if (Arbiter->PossibleAllocation)
{
    RtlFreeRangeList(Arbiter->PossibleAllocation);
    RtlInitializeRangeList(Arbiter->PossibleAllocation);
}

if (Arbiter->MutexEvent)
    KeSetEvent(Arbiter->MutexEvent, 0, FALSE);

return STATUS_SUCCESS;

}

/* FIXME: the prototype is not correct yet. */

CODE_SEG("PAGE")

NTSTATUS

NTAPI

ArbAddReserved(

In PARBITER_INSTANCE Arbiter)

{

PAGED_CODE();

复制代码
/* Add a reserved entry to the reserved list */
if (Arbiter->ReservedList.Orderings)
{
    /* Find the last reserved entry and extend it */
    ULONG idx = Arbiter->ReservedList.Count;
    if (idx < Arbiter->ReservedList.Maximum)
    {
        /* Reserve from address 0 to the max of existing ranges */
        Arbiter->ReservedList.Orderings[idx].Start = 0;
        Arbiter->ReservedList.Orderings[idx].End = (ULONGLONG)-1;
        Arbiter->ReservedList.Count++;
    }
}

return STATUS_SUCCESS;

}

CODE_SEG("PAGE")

NTSTATUS

NTAPI

ArbPreprocessEntry(

In PARBITER_INSTANCE Arbiter,

Inout PARBITER_ALLOCATION_STATE ArbState)

{

PARBITER_LIST_ENTRY ListEntry;

PIO_RESOURCE_DESCRIPTOR IoDescriptor;

UINT64 MinAddr, MaxAddr;

UINT32 Length, Alignment;

NTSTATUS Status;

复制代码
PAGED_CODE();

/* Get the list entry from the allocation state */
ListEntry = ArbState->Entry;
if (!ListEntry)
    return STATUS_INVALID_PARAMETER;

/* Check if the arbiter has unpack requirement callback */
if (!Arbiter->UnpackRequirement)
    return STATUS_NOT_IMPLEMENTED;

/* If there are alternatives, pre-process them */
if (ListEntry->AlternativeCount > 0)
{
    /* Allocate space for alternatives array */
    ArbState->Alternatives = (PARBITER_ALTERNATIVE)ListEntry->Alternatives;
    ArbState->AlternativeCount = ListEntry->AlternativeCount;
    ArbState->CurrentAlternative = &ArbState->Alternatives[0];

    /* Parse the first alternative to initialize state */
    IoDescriptor = ArbState->CurrentAlternative->Descriptor;
    if (!IoDescriptor)
        return STATUS_INVALID_PARAMETER;

    /* Unpack the requirement to get address range and alignment */
    Status = Arbiter->UnpackRequirement(IoDescriptor,
                                        &MinAddr,
                                        &MaxAddr,
                                        &Length,
                                        &Alignment);
    if (!NT_SUCCESS(Status))
        return Status;

    /* Initialize the allocation state */
    ArbState->Start = MinAddr;
    ArbState->End = MaxAddr;
    ArbState->CurrentMinimum = ArbState->Start;
    ArbState->CurrentMaximum = ArbState->End;
}
else
{
    /* No alternatives available */
    ArbState->AlternativeCount = 0;
    ArbState->Alternatives = NULL;
    ArbState->CurrentAlternative = NULL;
    return STATUS_NO_MORE_ENTRIES;
}

return STATUS_SUCCESS;

}

CODE_SEG("PAGE")

NTSTATUS

NTAPI

ArbAllocateEntry(

In PARBITER_INSTANCE Arbiter,

Inout PARBITER_ALLOCATION_STATE ArbState)

{

NTSTATUS Status;

BOOLEAN HasRange;

BOOLEAN FoundSuitable;

复制代码
PAGED_CODE();

/* Preprocess the entry to initialize the allocation state */
Status = ArbPreprocessEntry(Arbiter, ArbState);
if (!NT_SUCCESS(Status))
{
    /* If no alternatives available, return the status */
    if (Status == STATUS_NO_MORE_ENTRIES)
        return STATUS_NO_MORE_ENTRIES;
    return Status;
}

/* Main allocation loop: try ranges and alternatives */
while (TRUE)
{
    /* Get the next available allocation range */
    HasRange = ArbGetNextAllocationRange(Arbiter, ArbState);
    if (!HasRange)
    {
        /* No more ranges available, try to backtrack */
        /* If we have no previous allocations to backtrack, fail */
        DPRINT("ArbAllocateEntry: No more allocation ranges\n");
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    /* Try to find a suitable address within this range */
    FoundSuitable = ArbFindSuitableRange(Arbiter, ArbState);
    if (FoundSuitable)
    {
        /* Commit the allocation */
        ArbAddAllocation(Arbiter, ArbState);
        return STATUS_SUCCESS;
    }

    /* Continue to next range */
}

return STATUS_INSUFFICIENT_RESOURCES;

}

CODE_SEG("PAGE")

BOOLEAN

NTAPI

ArbGetNextAllocationRange(

In PARBITER_INSTANCE Arbiter,

Inout PARBITER_ALLOCATION_STATE ArbState)

{

PIO_RESOURCE_DESCRIPTOR IoDescriptor;

UINT64 MinAddr, MaxAddr;

UINT32 Length, Alignment;

UINT64 RangeStart, RangeEnd;

NTSTATUS Status;

复制代码
PAGED_CODE();

/* Check if we have a current alternative */
if (!ArbState->CurrentAlternative)
    return FALSE;

/* Get the current alternative's descriptor */
IoDescriptor = ArbState->CurrentAlternative->Descriptor;
if (!IoDescriptor)
    return FALSE;

/* Unpack the requirement */
Status = Arbiter->UnpackRequirement(IoDescriptor,
                                    &MinAddr,
                                    &MaxAddr,
                                    &Length,
                                    &Alignment);
if (!NT_SUCCESS(Status))
    return FALSE;

/* Search through ordering list to find a range that can satisfy this request */
/* We iterate the ordering list and check against PossibleAllocation */
{
    ULONG i;
    BOOLEAN Found = FALSE;

    for (i = 0; i < Arbiter->OrderingList.Count; i++)
    {
        RangeStart = Arbiter->OrderingList.Orderings[i].Start;
        RangeEnd = Arbiter->OrderingList.Orderings[i].End;

        /* Clip range to what the alternative allows */
        if (RangeStart < MinAddr)
            RangeStart = MinAddr;
        if (RangeEnd > MaxAddr)
            RangeEnd = MaxAddr;

        /* Check if we have a valid range */
        if (RangeStart <= RangeEnd)
        {
            /* Check if this range has available space using range list */
            if (Arbiter->PossibleAllocation)
            {
                BOOLEAN Available;
                Status = RtlIsRangeAvailable(Arbiter->PossibleAllocation,
                                             RangeStart,
                                             RangeEnd,
                                             0,
                                             0,
                                             NULL,
                                             NULL,
                                             &Available);
                if (NT_SUCCESS(Status) && Available)
                {
                    /* Found an available range */
                    ArbState->CurrentMinimum = RangeStart;
                    ArbState->CurrentMaximum = RangeEnd;
                    Found = TRUE;
                    break;
                }
            }
            else
            {
                /* No allocation tracking yet, use the full range */
                ArbState->CurrentMinimum = RangeStart;
                ArbState->CurrentMaximum = RangeEnd;
                Found = TRUE;
                break;
            }
        }
    }

    if (!Found)
    {
        /* Try next alternative if available */
        ULONG AltIndex = (ULONG)(ArbState->CurrentAlternative - ArbState->Alternatives);
        AltIndex++;

        if (AltIndex < ArbState->AlternativeCount)
        {
            ArbState->CurrentAlternative = &ArbState->Alternatives[AltIndex];
            return ArbGetNextAllocationRange(Arbiter, ArbState);
        }

        return FALSE;
    }
}

return TRUE;

}

CODE_SEG("PAGE")

BOOLEAN

NTAPI

ArbFindSuitableRange(

In PARBITER_INSTANCE Arbiter,

Inout PARBITER_ALLOCATION_STATE ArbState)

{

UINT32 Alignment, Length;

PIO_RESOURCE_DESCRIPTOR IoDescriptor;

UINT64 MinAddr, MaxAddr;

NTSTATUS Status;

UINT64 TestAddress;

复制代码
PAGED_CODE();

/* Check if we have a current alternative */
if (!ArbState->CurrentAlternative)
    return FALSE;

/* Get the descriptor */
IoDescriptor = ArbState->CurrentAlternative->Descriptor;
if (!IoDescriptor)
    return FALSE;

/* Unpack to get alignment and length */
Status = Arbiter->UnpackRequirement(IoDescriptor,
                                    &MinAddr,
                                    &MaxAddr,
                                    &Length,
                                    &Alignment);
if (!NT_SUCCESS(Status))
    return FALSE;

/* Find a suitable address within the current range */
/* Start from the maximum address and work downward (high-to-low allocation) */
TestAddress = ArbState->CurrentMaximum;

/* Apply alignment */
if (Alignment > 1)
    TestAddress = (TestAddress / (UINT64)Alignment) * (UINT64)Alignment;

/* Check if we have enough space */
if (TestAddress < ArbState->CurrentMinimum ||
    (TestAddress - ArbState->CurrentMinimum + 1) < Length)
{
    return FALSE;
}

/* Set the found address in the allocation state */
ArbState->Start = TestAddress - (Length - 1);
ArbState->End = TestAddress;

return TRUE;

}

CODE_SEG("PAGE")

VOID

NTAPI

ArbAddAllocation(

In PARBITER_INSTANCE Arbiter,

Inout PARBITER_ALLOCATION_STATE ArbState)

{

PAGED_CODE();

复制代码
/* Add the allocated range to the arbiter's allocation list */
if (Arbiter->Allocation)
{
    RtlAddRange(Arbiter->Allocation,
                ArbState->Start,
                ArbState->End,
                0, /* Attributes */
                0, /* Flags */
                NULL, /* UserData */
                ArbState->Entry); /* Owner = the list entry */
}

/* Remove the allocated range from possible allocation list */
if (Arbiter->PossibleAllocation)
{
    RtlDeleteRange(Arbiter->PossibleAllocation,
                   ArbState->Start,
                   ArbState->End,
                   ArbState->Entry);
}

/* Record the allocation on the stack for potential backtracking */
if (Arbiter->AllocationStack)
{
    ULONG StackIndex = 0;

    /* Find the next free slot in the allocation stack */
    /* The allocation stack tracks the order of allocations for backtracking */
    /* We use a simple sequential index stored in the state's workspace */
    StackIndex = (ULONG)ArbState->WorkSpace;
    ArbState->WorkSpace = (LONG_PTR)(StackIndex + 1);
}

}

CODE_SEG("PAGE")

VOID

NTAPI

ArbBacktrackAllocation(

In PARBITER_INSTANCE Arbiter,

Inout PARBITER_ALLOCATION_STATE ArbState)

{

PAGED_CODE();

复制代码
/* Remove the last allocation from the allocation list */
if (Arbiter->Allocation && ArbState->Entry)
{
    RtlDeleteRange(Arbiter->Allocation,
                   ArbState->Start,
                   ArbState->End,
                   ArbState->Entry);
}

/* Restore the range back to possible allocation list */
if (Arbiter->PossibleAllocation)
{
    RtlAddRange(Arbiter->PossibleAllocation,
                ArbState->Start,
                ArbState->End,
                0,
                0,
                NULL,
                NULL);
}

/* Decrement the stack workspace index */
if (ArbState->WorkSpace > 0)
{
    ArbState->WorkSpace--;
}

}

/* FIXME: the prototype is not correct yet. */

CODE_SEG("PAGE")

NTSTATUS

NTAPI

ArbOverrideConflict(

In PARBITER_INSTANCE Arbiter)

{

PAGED_CODE();

复制代码
/* Force-allow the current allocation despite conflicts.
   This is used when a device is already configured by BIOS
   and we want to keep its current resource assignment. */

/* Mark the arbiter as allowing overrides */
Arbiter->TransactionInProgress = TRUE;

return STATUS_SUCCESS;

}

CODE_SEG("PAGE")

NTSTATUS

NTAPI

ArbBootAllocation(

In PARBITER_INSTANCE Arbiter,

In PLIST_ENTRY ArbitrationList)

{

PLIST_ENTRY Entry;

PARBITER_LIST_ENTRY ListEntry;

ARBITER_ALLOCATION_STATE ArbState;

NTSTATUS Status;

复制代码
PAGED_CODE();

/* Lock the arbiter */
if (Arbiter->MutexEvent)
    KeWaitForSingleObject(Arbiter->MutexEvent, Executive, KernelMode, FALSE, NULL);

/* Iterate through the arbitration list and try to allocate */
Entry = ArbitrationList->Flink;
while (Entry != ArbitrationList)
{
    ListEntry = CONTAINING_RECORD(Entry, ARBITER_LIST_ENTRY, ListEntry);

    RtlZeroMemory(&ArbState, sizeof(ARBITER_ALLOCATION_STATE));
    ArbState.Entry = ListEntry;

    Status = ArbAllocateEntry(Arbiter, &ArbState);

    if (!NT_SUCCESS(Status))
    {
        DPRINT1("ArbBootAllocation: Failed to allocate entry %p, Status %x\n",
                ListEntry, Status);
        /* Continue trying other entries - boot allocation is best-effort */
    }

    Entry = Entry->Flink;
}

if (Arbiter->MutexEvent)
    KeSetEvent(Arbiter->MutexEvent, 0, FALSE);

return STATUS_SUCCESS;

}

/* FIXME: the prototype is not correct yet. */

CODE_SEG("PAGE")

NTSTATUS

NTAPI

ArbQueryConflict(

In PARBITER_INSTANCE Arbiter)

{

PAGED_CODE();

复制代码
/* This function should check if there's a conflict in the current
   allocation list. In a full implementation, this would take a
   resource descriptor and check against the Allocation list. */

/* For now, return no conflict */
return STATUS_SUCCESS;

}

/* FIXME: the prototype is not correct yet. */

CODE_SEG("PAGE")

NTSTATUS

NTAPI

ArbStartArbiter(

In PARBITER_INSTANCE Arbiter)

{

PAGED_CODE();

复制代码
/* Verify the arbiter is properly initialized */
if (Arbiter->Signature != ARBITER_SIGNATURE)
{
    DPRINT1("ArbStartArbiter: Invalid signature\n");
    return STATUS_INVALID_PARAMETER;
}

/* Verify critical fields are set */
if (!Arbiter->Allocation || !Arbiter->PossibleAllocation)
{
    DPRINT1("ArbStartArbiter: Allocation lists not initialized\n");
    return STATUS_INVALID_PARAMETER;
}

/* Check if we need a boot allocation */
if (Arbiter->OrderingList.Count == 0)
{
    /* No ordering set up, try to build one */
    DPRINT1("ArbStartArbiter: No ordering list, arbiter not ready\n");
    return STATUS_UNSUCCESSFUL;
}

return STATUS_SUCCESS;

}

CODE_SEG("PAGE")

NTSTATUS

NTAPI

ArbAddOrdering(

Out PARBITER_ORDERING_LIST OrderList,

In UINT64 MinimumAddress,

In UINT64 MaximumAddress)

{

PARBITER_ORDERING NewOrderings;

ULONG NewMaximum;

复制代码
PAGED_CODE();

/* Make sure the range is valid */
if (MinimumAddress > MaximumAddress)
    return STATUS_INVALID_PARAMETER;

/* Check if we need to grow the list */
if (OrderList->Count >= OrderList->Maximum)
{
    /* Double the list size, or use initial count */
    NewMaximum = OrderList->Maximum ? (OrderList->Maximum * 2) : INITIAL_ORDERING_COUNT;
    NewOrderings = ExAllocatePoolWithTag(PagedPool,
                                         NewMaximum * sizeof(ARBITER_ORDERING),
                                         TAG_ARBITER);
    if (!NewOrderings)
        return STATUS_INSUFFICIENT_RESOURCES;

    /* Copy existing entries if any */
    if (OrderList->Orderings && OrderList->Count)
    {
        RtlCopyMemory(NewOrderings,
                      OrderList->Orderings,
                      OrderList->Count * sizeof(ARBITER_ORDERING));
    }

    /* Free old list if it was allocated by us */
    if (OrderList->Orderings)
        ExFreePoolWithTag(OrderList->Orderings, TAG_ARBITER);

    OrderList->Orderings = NewOrderings;
    OrderList->Maximum = NewMaximum;
}

/* Add the new ordering entry */
OrderList->Orderings[OrderList->Count].Start = MinimumAddress;
OrderList->Orderings[OrderList->Count].End = MaximumAddress;
OrderList->Count++;

return STATUS_SUCCESS;

}

CODE_SEG("PAGE")

NTSTATUS

NTAPI

ArbPruneOrdering(

Out PARBITER_ORDERING_LIST OrderingList,

In UINT64 MinimumAddress,

In UINT64 MaximumAddress)

{

ULONG i, WriteIndex;

UINT64 NewStart, NewEnd;

复制代码
PAGED_CODE();

/* Prune the ordering list in-place */
WriteIndex = 0;
for (i = 0; i < OrderingList->Count; i++)
{
    NewStart = OrderingList->Orderings[i].Start;
    NewEnd = OrderingList->Orderings[i].End;

    /* Clip the start to the valid range */
    if (NewStart < MinimumAddress)
        NewStart = MinimumAddress;

    /* Clip the end to the valid range */
    if (NewEnd > MaximumAddress)
        NewEnd = MaximumAddress;

    /* Keep the range only if it still has valid size */
    if (NewStart <= NewEnd)
    {
        OrderingList->Orderings[WriteIndex].Start = NewStart;
        OrderingList->Orderings[WriteIndex].End = NewEnd;
        WriteIndex++;
    }
}

/* Update the count */
OrderingList->Count = WriteIndex;

return STATUS_SUCCESS;

}

CODE_SEG("PAGE")

NTSTATUS

NTAPI

ArbInitializeOrderingList(

Out PARBITER_ORDERING_LIST OrderList)

{

PAGED_CODE();

复制代码
/* Initialize the ordering list */
OrderList->Count = 0;
OrderList->Maximum = 0;
OrderList->Orderings = NULL;

return STATUS_SUCCESS;

}

CODE_SEG("PAGE")

VOID

NTAPI

ArbFreeOrderingList(

Out PARBITER_ORDERING_LIST OrderList)

{

PAGED_CODE();

复制代码
/* Free the ordering array if it was allocated */
if (OrderList->Orderings)
{
    ExFreePoolWithTag(OrderList->Orderings, TAG_ARBITER);
    OrderList->Orderings = NULL;
}

/* Reset the list */
OrderList->Count = 0;
OrderList->Maximum = 0;

}

CODE_SEG("PAGE")

NTSTATUS

NTAPI

ArbBuildAssignmentOrdering(

Inout PARBITER_INSTANCE ArbInstance,

In PCWSTR OrderName,

In PCWSTR ReservedOrderName,

In PARB_TRANSLATE_ORDERING TranslateOrderingFunction)

{

NTSTATUS Status;

复制代码
PAGED_CODE();

/* Free existing ordering lists */
ArbFreeOrderingList(&ArbInstance->OrderingList);
ArbFreeOrderingList(&ArbInstance->ReservedList);
switch (ArbInstance->ResourceType)
{
    case CmResourceTypeInterrupt:
        /* IRQ range: 0-255 (typical x86 PIC) or 0-255 (APIC) */
        Status = ArbAddOrdering(&ArbInstance->OrderingList, 0, 255);
        break;

    case CmResourceTypeDma:
        /* DMA range: 0-7 (typical ISA DMA) or 0-15 (EISA) */
        Status = ArbAddOrdering(&ArbInstance->OrderingList, 0, 15);
        break;

    case CmResourceTypePort:
        /* I/O Port range: 0x0000-0xFFFF */
        Status = ArbAddOrdering(&ArbInstance->OrderingList, 0, 0xFFFF);
        break;

    case CmResourceTypeMemory:
        /* Memory range: full address space */
        Status = ArbAddOrdering(&ArbInstance->OrderingList, 0, (ULONGLONG)-1);
        break;

    case CmResourceTypeBusNumber:
        /* Bus number range: 0-255 */
        Status = ArbAddOrdering(&ArbInstance->OrderingList, 0, 255);
        break;

    default:
        /* Unknown resource type, create a minimal ordering */
        Status = ArbAddOrdering(&ArbInstance->OrderingList, 0, (ULONGLONG)-1);
        break;
}

if (!NT_SUCCESS(Status))
    return Status;

/* Handle reserved ordering if a reserved name was provided */
if (ReservedOrderName && ReservedOrderName[0] != L'\0')
{
    /* For reserved resources, we use an empty list initially.
       Reserved resources will be added later via ArbAddReserved. */
    Status = ArbAddOrdering(&ArbInstance->ReservedList, 0, 0);
    if (!NT_SUCCESS(Status))
    {
        ArbFreeOrderingList(&ArbInstance->OrderingList);
        return Status;
    }
}

return STATUS_SUCCESS;

}

CODE_SEG("PAGE")

NTSTATUS

NTAPI

ArbInitializeArbiterInstance(

Inout PARBITER_INSTANCE Arbiter,

In PDEVICE_OBJECT BusDeviceObject,

In CM_RESOURCE_TYPE ResourceType,

In PCWSTR ArbiterName,

In PCWSTR OrderName,

In PARB_TRANSLATE_ORDERING TranslateOrderingFunction)

{

NTSTATUS Status;

复制代码
PAGED_CODE();

DPRINT("ArbInitializeArbiterInstance: '%S'\n", ArbiterName);

ASSERT(Arbiter->UnpackRequirement != NULL);
ASSERT(Arbiter->PackResource != NULL);
ASSERT(Arbiter->UnpackResource != NULL);
ASSERT(Arbiter->MutexEvent == NULL);
ASSERT(Arbiter->Allocation == NULL);
ASSERT(Arbiter->PossibleAllocation == NULL);
ASSERT(Arbiter->AllocationStack == NULL);

Arbiter->Signature = ARBITER_SIGNATURE;
Arbiter->BusDeviceObject = BusDeviceObject;

Arbiter->MutexEvent = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), TAG_ARBITER);
if (!Arbiter->MutexEvent)
{
    DPRINT1("ArbInitializeArbiterInstance: STATUS_INSUFFICIENT_RESOURCES\n");
    return STATUS_INSUFFICIENT_RESOURCES;
}

KeInitializeEvent(Arbiter->MutexEvent, SynchronizationEvent, TRUE);

Arbiter->AllocationStack = ExAllocatePoolWithTag(PagedPool, PAGE_SIZE, TAG_ARB_ALLOCATION);
if (!Arbiter->AllocationStack)
{
    DPRINT1("ArbInitializeArbiterInstance: STATUS_INSUFFICIENT_RESOURCES\n");
    ExFreePoolWithTag(Arbiter->MutexEvent, TAG_ARBITER);
    return STATUS_INSUFFICIENT_RESOURCES;
}

Arbiter->AllocationStackMaxSize = PAGE_SIZE;

Arbiter->Allocation = ExAllocatePoolWithTag(PagedPool, sizeof(RTL_RANGE_LIST), TAG_ARB_RANGE);
if (!Arbiter->Allocation)
{
    DPRINT1("ArbInitializeArbiterInstance: STATUS_INSUFFICIENT_RESOURCES\n");
    ExFreePoolWithTag(Arbiter->AllocationStack, TAG_ARB_ALLOCATION);
    ExFreePoolWithTag(Arbiter->MutexEvent, TAG_ARBITER);
    return STATUS_INSUFFICIENT_RESOURCES;
}

Arbiter->PossibleAllocation = ExAllocatePoolWithTag(PagedPool, sizeof(RTL_RANGE_LIST), TAG_ARB_RANGE);
if (!Arbiter->PossibleAllocation)
{
    DPRINT1("ArbInitializeArbiterInstance: STATUS_INSUFFICIENT_RESOURCES\n");
    ExFreePoolWithTag(Arbiter->Allocation, TAG_ARB_RANGE);
    ExFreePoolWithTag(Arbiter->AllocationStack, TAG_ARB_ALLOCATION);
    ExFreePoolWithTag(Arbiter->MutexEvent, TAG_ARBITER);
    return STATUS_INSUFFICIENT_RESOURCES;
}

RtlInitializeRangeList(Arbiter->Allocation);
RtlInitializeRangeList(Arbiter->PossibleAllocation);

Arbiter->Name = ArbiterName;
Arbiter->ResourceType = ResourceType;
Arbiter->TransactionInProgress = FALSE;

if (!Arbiter->TestAllocation)
    Arbiter->TestAllocation = ArbTestAllocation;

if (!Arbiter->RetestAllocation)
    Arbiter->RetestAllocation = ArbRetestAllocation;

if (!Arbiter->CommitAllocation)
    Arbiter->CommitAllocation = ArbCommitAllocation;

if (!Arbiter->RollbackAllocation)
    Arbiter->RollbackAllocation = ArbRollbackAllocation;

if (!Arbiter->AddReserved)
    Arbiter->AddReserved = ArbAddReserved;

if (!Arbiter->PreprocessEntry)
    Arbiter->PreprocessEntry = ArbPreprocessEntry;

if (!Arbiter->AllocateEntry)
    Arbiter->AllocateEntry = ArbAllocateEntry;

if (!Arbiter->GetNextAllocationRange)
    Arbiter->GetNextAllocationRange = ArbGetNextAllocationRange;

if (!Arbiter->FindSuitableRange)
    Arbiter->FindSuitableRange = ArbFindSuitableRange;

if (!Arbiter->AddAllocation)
    Arbiter->AddAllocation = ArbAddAllocation;

if (!Arbiter->BacktrackAllocation)
    Arbiter->BacktrackAllocation = ArbBacktrackAllocation;

if (!Arbiter->OverrideConflict)
    Arbiter->OverrideConflict = ArbOverrideConflict;

if (!Arbiter->BootAllocation)
    Arbiter->BootAllocation = ArbBootAllocation;

if (!Arbiter->QueryConflict)
    Arbiter->QueryConflict = ArbQueryConflict;

if (!Arbiter->StartArbiter)
    Arbiter->StartArbiter = ArbStartArbiter;

Status = ArbBuildAssignmentOrdering(Arbiter, OrderName, OrderName, TranslateOrderingFunction);
if (NT_SUCCESS(Status))
{
    return STATUS_SUCCESS;
}

DPRINT1("ArbInitializeArbiterInstance: Status %X\n", Status);

return Status;

}

  1. `
相关推荐
新手村领路人2 小时前
在macos python中安装dlib
开发语言·python·macos
郝学胜-神的一滴2 小时前
Qt 高级开发 024:QSplitter分裂器布局精讲
开发语言·c++·qt·程序人生·用户界面
晚风吹红霞2 小时前
深入浅出C++ STL:从入门到精通的核心指南
开发语言·c++
JAVA社区2 小时前
Java高级全套教程(十四)—— SpringData超详细实战详解
java·开发语言·spring cloud·面试·职场和发展
182******20832 小时前
2026年学C语言还有出路吗?学习需要报班吗?
c语言·开发语言·学习
-凌凌漆-3 小时前
【Qt】std::shared_ptr<>与std::make_shared<>
开发语言·qt
_阿伟_3 小时前
计算机知识科普
java·开发语言
ulias2123 小时前
深挖进程间通信的奥秘
java·linux·服务器·开发语言·c++·算法