通常,KMD) (显示微型端口驱动程序是可重入的。 也就是说,KMD 中可以同时存在多个线程。 但是,某些对 KMD 的调用不应是可重入的,因为它们要么访问图形硬件,要么访问全局跨线程数据结构。
尽管无法在按调用级别选择重入性或非进入性,但 WDDM 会预先分配每个调用的同步级别,这些级别准确定义了驱动程序对调用的预期。 这些同步级别如下所示:
- 线程处理和同步级别三
- 线程和同步级别二
- 线程处理和同步级别 1
- 线程和同步级别为零
- 线程同步和 TDR
一、同步级别定义矩阵
同步级别 | 线程安全要求 | 典型调用场景 | 硬件访问权限 |
---|---|---|---|
Level 3 | 完全非可重入 | DxgkDdiSetVidPnSourceAddress | 直接操作CRTC寄存器 |
Level 2 | 每设备单线程 | DxgkDdiSubmitCommand | 命令DMA缓冲区提交 |
Level 1 | 每上下文多线程 | DxgkDdiPatch | 资源描述符更新 |
Level 0 | 完全可重入 | DxgkDdiQueryAdapterInfo | 仅内存读取 |
TDR | 系统级独占访问 | DxgkDdiResetFromTimeout | 全设备复位 |
二、各级别实现规范
2.1 Level 3实现(硬件关键区)
NTSTATUS DxgkDdiSetVidPnSourceAddress(
_In_ CONST HANDLE hContext,
_In_ DXGKARG_SETVIDPNSOURCEADDRESS* pArgs)
{
// 自动获取设备级锁(DXGKRNL提供)
DXGKRNL_DEVICE_LOCK lock(hDevice);
// 直接写硬件寄存器
WRITE_REGISTER_ULONG(
pDevExt->pRegisters + CRTC_OFFSET,
pArgs->PrimaryAddress);
return STATUS_SUCCESS;
}
锁特性:
- 自旋锁实现(KeAcquireSpinLock)
- 禁止嵌套调用同一设备其他Level 3函数
2.2 Level 2同步(每设备单线程)
实现要点:
- 使用FAST_MUTEX保护设备全局状态
- 允许与Level 1调用并行
2.3 TDR特殊处理
void DxgkDdiResetFromTimeout(_In_ PVOID pContext) {
// 获取系统级TDR锁
KeEnterCriticalRegion();
ExAcquirePushLockExclusive(&gTdrLock);
// 强制终止所有设备上下文
ForEachContext(CTX_TERMINATE);
// 硬件冷复位
ResetGPU(pDevExt);
ExReleasePushLockExclusive(&gTdrLock);
KeLeaveCriticalRegion();
}
三、死锁预防策略
3.1 锁层级规则
TDR Lock (最高)
│
└─ Level 3 Device Lock
│
└─ Level 2 Fast Mutex
│
└─ Level 1 Context SpinLock
3.2 超时机制
#define LEVEL2_TIMEOUT_MS 500
LARGE_INTEGER timeout;
timeout.QuadPart = -LEVEL2_TIMEOUT_MS * 10000LL;
if (!ExTryAcquireFastMutex(&pDevExt->Level2Mutex, timeout)) {
TriggerTimeoutDetection();
}
四、调试辅助
4.1 WinDbg扩展命令
!dxgkd.synclevel 0x1 // 显示设备1的锁状态
!deadlock detect // 分析锁依赖环
4.2 ETW事件标记
EventWriteDXGK_SYNCLEVEL_ENTER(
pDevExt->DeviceHandle,
CurrentIrql(),
CallbackType);
五、版本兼容性
WDDM版本 | 新增约束 |
---|---|
1.2 | 明确Level 2必须支持并发Present |
2.0 | 引入Level 1每上下文细粒度锁 |
2.5 | TDR锁增加CPU核心亲和性限制 |
六、性能优化
6.1 锁选择策略
临界区长度 | 推荐锁类型 |
---|---|
<1μs | KSPIN_LOCK |
1-100μs | FAST_MUTEX |
>100μs | EX_PUSH_LOCK |
6.2锁模式示例
// Level 0查询优化
volatile LONG* pCounter = (volatile LONG*)pStats;
InterlockedIncrement(pCounter);
无附录:同步级别判定流程图
graph TD
A[回调进入] --> B{是否操作硬件?}
B -->|是| C[Level 3]
B -->|否| D{修改全局状态?}
D -->|是| E[Level 2]
D -->|否| F{上下文相关?}
F -->|是| G[Level 1]
F -->|否| H[Level 0]