window 显示驱动开发-线程和同步级别为零级

在零级线程处理和同步中,WDDM 允许以可重入的方式对显示微型端口驱动程序进行零级 DxgkDdi*Xxx 调用。 也就是说,多个线程可以通过调用零级 DDI 同时进入驱动程序。

驱动程序应预期系统中的任何线程会传入,并应相应地保护该线程的数据。

尽管驱动程序中可以同时运行两个或多个线程,但不能有两个线程属于单个进程。

级别零是默认的线程和同步级别,包括以下函数:

  • DxgkDdiCheckMultiPlaneOverlaySupport3 (或 DxgkDdiCheckMultiPlaneOverlaySupport2/DxgkDdiCheckMultiPlaneOverlaySupport)
  • DxgkDdiCloseAllocation
  • DxgkDdiCollectDbgInfo。 此函数应收集各种故障的调试信息,并且可以随时在高 IRQL (调用,也就是说, DxgkDdiCollectDbgInfo 运行所在的 IRQL 通常) 未定义。 在所有情况下, DxgkDdiCollectDbgInfo 都必须验证所需调试信息和正确同步的可用性。 但是,如果 pCollectDbgInfo 参数指向的 DXGKARG_COLLECTDBGINFO 结构的 Reason 成员设置为 VIDEO_TDR_TIMEOUT_DETECTED 或 VIDEO_ENGINE_TIMEOUT_DETECTED,则驱动程序必须确保 DxgkDdiCollectDbgInfo 可分页、在 IRQL = PASSIVE_LEVEL 运行并支持零级同步。
  • DxgkDdiControlEtwLogging
  • DxgkDdiCreateAllocation
  • DxgkDdiCreateContext
  • DxgkDdiCreateDevice
  • DxgkDdiDescribeAllocation
  • DxgkDdiDestroyAllocation
  • DxgkDdiDestroyContext
  • DxgkDdiDestroyDevice
  • DxgkDdiDpcRoutine
  • DxgkDdiEnumVidPnCofuncModality
  • DxgkDdiGetScanLine
  • DxgkDdiGetStandardAllocationDriverData
  • DxgkDdiInterruptRoutine
  • DxgkDdiIsSupportedVidPn
  • DxgkDdiMiracastCreateContext
  • DxgkDdiMiracastDestroyContext
  • DxgkDdiMiracastIoControl
  • DxgkDdiMiracastQueryCaps
  • DxgkDdiOpenAllocation
  • DxgkDdiPresent
  • DxgkDdiQueryAdapterInfo
  • DxgkDdiQueryCurrentFence
  • DxgkDdiRecommendFunctionalVidPn
  • DxgkDdiRecommendVidPnTopology
  • DxgkDdiRender
  • DxgkDdiRenderKm
  • DxgkDdiResetDevice

1. 零级同步的核心特性

(1) 可重入性(Reentrancy)

  • 多个线程可同时调用零级 DDI 函数,但 同一进程的两个线程不能同时进入驱动程序(跨进程允许并发)。
  • 驱动程序必须 自行保护共享数据(如全局状态、硬件寄存器等),避免竞争条件。

(2) 默认同步级别

  • 零级是 默认级别,适用于大多数常规 DDI 调用。
  • 相比 Level 1/2/3,零级同步限制最少,但要求驱动程序 自行管理线程安全。

(3) IRQL 限制

  • 大多数零级函数可以在 任意 IRQL(中断请求级别)运行,但某些特殊情况(如 DxgkDdiCollectDbgInfo 处理超时)必须在 PASSIVE_LEVEL(低 IRQL)执行。

2. 零级包含的主要函数

以下是常见的零级 DDI 函数:

函数 描述
DxgkDdiCheckMultiPlaneOverlaySupport[2/3] 检查硬件是否支持多平面覆盖(MPO)
DxgkDdiCloseAllocation 关闭分配的资源(如显存)
DxgkDdiCollectDbgInfo 调试信息收集(关键函数,见下文)

3. 特殊函数:DxgkDdiCollectDbgInfo

(1) 一般情况

  • 可以在 任意 IRQL 调用(包括 DISPATCH_LEVEL 或更高)。
  • 必须验证数据可用性(如内存是否可分页)。
  • 必须同步访问共享资源(如日志缓冲区)。

(2) 超时检测(TDR/Engine Timeout)

当 DXGKARG_COLLECTDBGINFO.Reason 为以下值时:

  • VIDEO_TDR_TIMEOUT_DETECTED(GPU 超时)
  • VIDEO_ENGINE_TIMEOUT_DETECTED(引擎超时)

驱动必须:

  • 在 PASSIVE_LEVEL(低 IRQL)运行(可分页代码)。
  • 支持零级同步(允许多线程进入)。
  • 避免死锁(不能持有自旋锁等不可睡眠的锁)。

4. 线程安全实现建议

由于零级允许可重入调用,驱动程序必须:

使用适当的同步机制:

  • 自旋锁(Spin Lock):适用于高 IRQL(如 DISPATCH_LEVEL)。
  • 互斥体(Mutex):适用于 PASSIVE_LEVEL(可分页代码)。
  • 原子操作(Atomic Operations):适用于简单状态更新(如引用计数)。

避免全局状态污染:

  • 使用 线程局部存储(TLS) 或 上下文结构体 隔离不同线程的数据。

5. 典型应用场景

多线程资源管理:

  • 线程A调用 DxgkDdiCloseAllocation 释放资源,同时线程B调用 DxgkDdiCheckMultiPlaneOverlaySupport3 检查 MPO 支持。

调试信息收集:

  • 系统在 GPU 超时(TDR)时调用 DxgkDdiCollectDbgInfo,同时其他线程可能仍在提交命令。

6. 总结

特性 零级(Level 0) 一级(Level 1) 二级(Level 2) 三级(Level 3)
可重入性 ✅ 允许(跨进程) ❌ 类内禁止 ❌ 单线程 ❌ 单线程
默认级别 ✅ 是 ❌ 否 ❌ 否 ❌ 否
IRQL 限制 大多数任意 IRQL 通常 PASSIVE_LEVEL 硬件空闲时 硬件空闲时
同步要求 驱动自行管理 类内互斥 WDDM 保证单线程 WDDM 保证单线程

零级同步适用于大多数常规操作,但驱动程序必须自行处理线程安全!

相关推荐
码兄科技5 小时前
Java AI智能体开发实战:从零构建智能对话系统指南
java·开发语言·人工智能
折哥的程序人生 · 物流技术专研6 小时前
第8篇:六大设计原则在工厂模式中的体现
java·设计模式·设计原则·工厂模式·编程进阶·扩充系列
小明bishe187 小时前
计算机毕业设计之基于JAVA的植物科普网站
java·spring boot·spring·架构·课程设计
Drone_xjw7 小时前
从 GDB 到 CDB:C/C++ 程序调试的两把“手术刀”
c语言·开发语言·c++
r_oo_ki_e_7 小时前
Java Map 集合学习笔记
java·笔记·学习
SL-staff7 小时前
智慧园区2000+设备统一管理:JVS-IoT如何降低运维成本40%
java·开发语言·物联网·智慧园区·设备管理·运维优化·jvs-iot
咖啡八杯8 小时前
GoF设计模式——模板方法模式
java·后端·spring·设计模式
爱笑的源码基地8 小时前
一款全开源的信创云PACS影像云平台解决方案,支持多模态医学影像处理(CT/MR/DR/超声/病理等)
java·源码·国产化·pacs·云影像·区域pacs
我命由我123459 小时前
Android 开发问题:ClickableSpan 的点击事件没有生效
java·java-ee·android studio·android jetpack·android-studio·android runtime
2zcode9 小时前
基于MATLAB图像处理的饮料瓶灌装液位检测系统设计与实现
开发语言·图像处理·matlab