Windows存储驱动开发(五):Storport驱动Win10到Win11架构迁移

Storport 驱动 Win10 到 Win11 架构迁移:多线程到单线程多任务

日期: 2026-03-08
项目: Bayhub SD Host Controller Storport 驱动
背景: Windows Storport DDI 限制导致架构重构


目录

  1. 背景:DDI 限制与架构挑战
  2. 架构对比
  3. 核心改动解析
  4. 实现细节
  5. 共享任务计数器机制
  6. 调试与问题排查
  7. 参考资料

1. 背景:DDI 限制与架构挑战

1.1 Storport HwStorPortProhibitedDDI 规则

根据 Microsoft 官方文档,Storport 微型端口驱动禁止调用大量 WDM DDI 函数:

1
2
3
4
5
6
禁止的 DDI 类型:
- Ke* 系列(KeWaitForSingleObject, KeInitializeSpinLock 等)
- Ex* 系列(ExAllocatePool, ExAcquireFastMutex 等)
- Io* 系列(IoCompleteRequest, IoCallDriver 等)
- Mm* 系列(MmAllocateNonCachedMemory 等)
- Ps* 系列(PsCreateSystemThread 等)

1.2 多线程架构的问题

原 Win10 架构使用 #ifdef MultiThread 启用的多线程模式存在以下问题:

问题 说明
线程同步复杂 需要 KeWaitForSingleObjectKeInitializeMutex 等被禁止的 DDI
资源竞争 多线程访问共享资源需要大量锁机制
Storport 不原生支持 Storport 设计为单线程回调模型
调试困难 线程间 race condition 难以复现

1.3 迁移目标

1
2
3
Win10: 多线程架构 (MultiThread)
↓ 重构
Win11: 单线程多任务架构 (Single-thread Multi-task)

2. 架构对比

2.1 Win10 多线程架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
┌─────────────────────────────────────────────────────────────────┐
│ Win10 架构 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Thread 0 │ │ Thread 1 │ │ Thread N │ │
│ │ (主线程) │ │ (Card Init) │ │ (其他) │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ └──────────────────┼──────────────────┘ │
│ │ │
│ ┌───────┴───────┐ │
│ │ Task Manager │ │
│ │ - TASK_CARD_CHG │
│ │ - TASK_TAG_IO │
│ │ - TASK_GEN_IO │
│ │ - ... │
│ └───────────────┘ │
│ │
│ 问题: 需要 KeWaitForMultipleObjects 等禁止的 DDI │
└─────────────────────────────────────────────────────────────────┘

2.2 Win11 单线程多任务架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
┌─────────────────────────────────────────────────────────────────┐
│ Win11 架构 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────┐│
│ │ 单个主线程 ││
│ │ ││
│ │ os_wait_event() ──→ switch(evt) ──→ process_task() ││
│ │ │ │ │ ││
│ │ │ ┌──────┴──────┐ │ ││
│ │ │ │ │ │ ││
│ │ │ ┌─────┴─────┐ ┌────┴────┐ ┌───┴───┐ ││
│ │ │ │EVENT_CARD │ │EVENT_TAG│ │EVENT_ │ ... ││
│ │ │ │ _CHG │ │ _IO │ │GEN_IO │ ││
│ │ │ └───────────┘ └─────────┘ └───────┘ ││
│ │ │ ││
│ └─────────┼──────────────────────────────────────────────────────┘│
│ │ │
│ ┌──────┴──────┐ │
│ │ Event Array │ (StorPort 兼容方式) │
│ │ pevt_array[]│ │
│ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘

2.3 关键差异

维度 Win10 多线程 Win11 单线程多任务
线程数 多线程 (MultiThread) 单线程
任务调度 Task Manager + 多事件 switch-case 直连
同步原语 KeWait*, ExAcquire* StorPortWaitForSingleObject
内存分配 ExAllocatePool StorPort* API
DDI 限制 违反 Storport DDI 符合 Storport DDI

3. 核心改动解析

3.1 移除 MultiThread 编译选项

Win10 代码 (thread.c):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#ifdef MultiThread
if (card->card_type == CARD_ERROR)
{
result = REQ_RESULT_NO_CARD;
goto exit;
}
//set card_init event
DbgInfo(MODULE_MAIN_THR, FEATURE_THREAD_TRACE, NOT_TO_RAM, "%s set EVENT_CARD_INIT\n", __FUNCTION__);
os_set_event(pdx, &pdx->os, EVENT_CARD_INIT);

//wait for card_init complete
while (pdx->card.thread_init_card_flag == 0)
{
StorPortStallExecution(50);
}
...
#else
if (thread_init_card(pdx, FALSE, TRUE, 3) == FALSE)
{
result = REQ_RESULT_NO_CARD;
}
#endif // MultiThread

Win11 代码 (移除 #ifdef MultiThread):

1
2
3
4
5
6
7
8
9
10
11
12
if (card->card_type == CARD_ERROR)
{
result = REQ_RESULT_NO_CARD;
goto exit;
}
//set card_init event
os_set_event(pdx, &pdx->os, EVENT_CARD_INIT);
//wait for card_init complete
while (pdx->card.thread_init_card_flag == 0)
{
StorPortStallExecution(50);
}

3.2 简化事件设置 API

Win10 API 签名:

1
2
3
4
5
6
7
8
9
10
11
12
// 包含 taskid 参数,用于 Task Manager
void os_set_event(void * pdx, os_struct * os, e_event_t event, e_task_t taskid)
{
win_set_task(&os->task_mgr, taskid, TASK_STATUS_OCCUR);
p = win_get_evt(&os->evt_mgr, event);
if(NULL != p)
{
DbgInfo(MODULE_OS_API, FEATURE_THREAD_TRACE, NOT_TO_RAM,
"%s set evt=%x, taskid=%x\n", __FUNCTION__, event, taskid);
StorPortIssueDpc((bht_dev_ext_t*) pdx, &p->dpc, p, NULL);
}
}

Win11 API 签名:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 直接设置事件,无需 Task Manager
void os_set_event(void * pdx, os_struct * os, e_event_t event)
{
win_evt_t * p = 0;
if(os->dump_mode)
return;

p = win_get_evt(&os->evt_mgr, event);
if(NULL != p)
{
DbgInfo(MODULE_OS_API, FEATURE_THREAD_TRACE, NOT_TO_RAM,
"%s set evt %x\n", __FUNCTION__, event);
StorPortIssueDpc((bht_dev_ext_t*) pdx, &p->dpc, p, NULL);
}
}

3.3 主循环重构

Win10 主循环 (Task Manager 模式):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
void thread_main(void * param)
{
bht_dev_ext_t * pdx = (bht_dev_ext_t *)param;
os_struct * os = &pdx->os;
e_event_t evt = EVENT_NONE;

for(;;)
{
evt = os_wait_event(pdx, os);
os_clear_event((void *) pdx, os, evt);

// 处理 task 依次顺序执行,有优先级,index 小的优先处理
for(u8 i = 0; i < os->task_mgr.task_cnt; ++i){
if(os->task_mgr.tasks[i].status == TASK_STATUS_OCCUR){
DbgInfo(MODULE_MAIN_THR, FEATURE_THREAD_TRACE, NOT_TO_RAM,
"task processing, task_id=%d\n", i);

os->task_mgr.tasks[i].status = TASK_STATUS_IDLE;
if(process_task(i, pdx, os))
goto exit; // special case for terminate thread task

DbgInfo(MODULE_MAIN_THR, FEATURE_THREAD_TRACE, NOT_TO_RAM,
"task done, task_id=%d\n", i);
}
}
}
exit:
DbgInfo(MODULE_MAIN_THR, FEATURE_DRIVER_INIT, NOT_TO_RAM, "exit thread_main\n");
}

Win11 主循环 (switch-case 模式):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
void thread_main(void * param)
{
bht_dev_ext_t * pdx = (bht_dev_ext_t *)param;
os_struct * os = &pdx->os;
e_event_t evt = EVENT_NONE;

for(;;)
{
DbgInfo(MODULE_MAIN_THR, FEATURE_THREAD_TRACE, NOT_TO_RAM, "thread wait evt\n");
evt = os_wait_event(pdx, os);
os_clear_event((void *) pdx, os, evt);
DbgInfo(MODULE_MAIN_THR, FEATURE_THREAD_TRACE, NOT_TO_RAM, "Thr get Event=%d\n", evt);

switch(evt)
{
case EVENT_CARD_CHG:
os_set_dev_busy(pdx);
if(pdx->pm_state.rtd3_en && pdx->pm_state.rtd3_entered)
break;
if(pdx->testcase.test_type == 0)
thread_handle_card_event(pdx);
else
testcase_main(pdx, 1);
os_set_dev_idle(pdx);
break;
case EVENT_TERMINATE:
DbgInfo(MODULE_MAIN_THR, FEATURE_THREAD_TRACE, TO_RAM, "terminal task\n");
goto exit;
case EVENT_TAG_IO:
calc_thr_start(&pdx->tick);
thread_tag_io(pdx);
DbgInfo(MODULE_MAIN_THR, FEATURE_RW_TRACE, NOT_TO_RAM, "rw evt task\n");
break;
case EVENT_GEN_IO:
thread_gen_io(pdx);
DbgInfo(MODULE_MAIN_THR, FEATURE_IOCTL_TRACE, NOT_TO_RAM, "io_ctl task\n");
break;
// ... 其他事件处理
}

DbgInfo(MODULE_MAIN_THR, FEATURE_THREAD_TRACE, NOT_TO_RAM, "Thr done Event=%d\n", evt);
}
exit:
DbgInfo(MODULE_MAIN_THR, FEATURE_DRIVER_INIT, NOT_TO_RAM, "exit thread\n");
}

3.4 事件等待机制

Win11 改进的事件等待:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
e_event_t os_wait_event(void * pdx, os_struct * os)
{
u32 i;
LARGE_INTEGER time_out;
evt_mgr_t * mgr = &os->evt_mgr;

time_out.QuadPart = 0; // 立即返回模式

if(os->dump_mode)
return EVENT_NONE;

do {
for (i = 0; i < mgr->evt_cnt; i++)
{
ret = StorPortWaitForSingleObject((bht_dev_ext_t*)pdx,
mgr->pevt_array[i], FALSE, &time_out);
if (ret == STOR_STATUS_SUCCESS)
goto exit;
}
// thread sleep 1 ms,避免 CPU 忙等
os_sleep(pdx, 1);
} while (1);

exit:
// 根据索引映射回事件类型
switch(i)
{
case EVT_WAIT_CARD_CHG: return EVENT_CARD_CHG;
case EVT_WAIT_CARD_INIT: return EVENT_CARD_INIT;
case EVT_WAIT_RW_REQUEST: return EVENT_TAG_IO;
case EVT_WAIT_IOCTL_REQUEST:return EVENT_GEN_IO;
case EVT_WAIT_RUNTIME_D3: return EVENT_RUNTIME_D3;
case EVT_WAIT_AUTO_TIMER: return EVENT_AUTO_TIMER;
case EVT_WAIT_SDIO: return EVENT_SDIO;
case EVT_WAIT_PENDING: return EVENT_PENDING;
case EVT_WAIT_TERMINAL: return EVENT_TERMINATE;
default: return EVENT_NONE;
}
}

4. 实现细节

4.1 事件初始化

Win11 简化的事件管理器初始化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
static void win_init_event_mgr(bht_dev_ext_t* pdx, evt_mgr_t *mgr)
{
DbgInfo(MODULE_OS_API, FEATURE_DRIVER_INIT, NOT_TO_RAM, "Enter %s\n", __FUNCTION__);

// 1. clean mgr
os_memset(mgr, 0, sizeof(evt_mgr_t));

// 2. init all evt - 直接初始化所有事件
win_init_event(pdx, mgr, win_get_evt(mgr, EVENT_CARD_CHG));
win_init_event(pdx, mgr, win_get_evt(mgr, EVENT_CARD_INIT));
win_init_event(pdx, mgr, win_get_evt(mgr, EVENT_TAG_IO));
win_init_event(pdx, mgr, win_get_evt(mgr, EVENT_GEN_IO));
win_init_event(pdx, mgr, win_get_evt(mgr, EVENT_RUNTIME_D3));
win_init_event(pdx, mgr, win_get_evt(mgr, EVENT_AUTO_TIMER));
win_init_event(pdx, mgr, win_get_evt(mgr, EVENT_PENDING));
win_init_event(pdx, mgr, win_get_evt(mgr, EVENT_TERMINATE));
win_init_event(pdx, mgr, win_get_evt(mgr, EVENT_SDIO));

DbgInfo(MODULE_OS_API, FEATURE_DRIVER_INIT, NOT_TO_RAM, "Exit %s\n", __FUNCTION__);
}

Win10 移除的 Task Manager 初始化 (Win11 不再需要):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Win10 代码 - Win11 已移除
static void win_init_task_mgr(bht_dev_ext_t* pdx, task_mgr_t *mgr)
{
os_memset(mgr, 0, sizeof(task_mgr_t));
// 此顺序要和 enum TASK_XXX 一致,且决定 main_thread 处理 task 的优先级
win_init_task(pdx, mgr, win_get_task(mgr, TASK_CARD_CHG));
win_init_task(pdx, mgr, win_get_task(mgr, TASK_TERMINATE));
win_init_task(pdx, mgr, win_get_task(mgr, TASK_PENDING));
win_init_task(pdx, mgr, win_get_task(mgr, TASK_TAG_IO));
win_init_task(pdx, mgr, win_get_task(mgr, TASK_GEN_IO));
win_init_task(pdx, mgr, win_get_task(mgr, TASK_RUNTIME_D3));
win_init_task(pdx, mgr, win_get_task(mgr, TASK_AUTO_TIMER));
win_init_task(pdx, mgr, win_get_task(mgr, TASK_SDIO));
win_init_task(pdx, mgr, win_get_task(mgr, TASK_CAMOD_POLL_CARD_CHG));
}

4.2 事件索引映射

Win11 显式的事件索引映射:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
static win_evt_t * win_get_evt(evt_mgr_t *mgr, e_event_t event)
{
int idx = 0;
switch(event)
{
case EVENT_CARD_CHG: idx = 0; break;
case EVENT_CARD_INIT: idx = 1; break;
case EVENT_TAG_IO: idx = 2; break;
case EVENT_GEN_IO: idx = 3; break;
case EVENT_RUNTIME_D3: idx = 4; break;
case EVENT_AUTO_TIMER: idx = 5; break;
case EVENT_PENDING: idx = 6; break;
case EVENT_TERMINATE: idx = 7; break;
case EVENT_SDIO: idx = 8; break;
default:
DbgErr("%s undefine evtID:%xh\n", __FUNCTION__, event);
return NULL;
}
return &mgr->evts[idx];
}

4.3 线程挂起/恢复

Win11 线程控制:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
bool os_pending_thread(void * pdx, bool pending)
{
// ...
os->thread[1].pending_lock = FALSE; // 注意:使用 thread[1] 而非 thread[0]
if(TRUE == pending)
{
ret = FALSE;
os_init_completion(pdx, &os->thread[0].break_pending);
os->thread[1].freeze = TRUE;
os_set_event(pdx, os, EVENT_PENDING);
while(i--)
{
if(TRUE == os->thread[1].pending_lock)
{
ret = TRUE;
break;
}
}
}
else
{
os_finish_completion(pdx, &os->thread[0].break_pending);
os->thread[1].freeze = FALSE;
}
// ...
}

5. 共享任务计数器机制

5.1 问题背景

卡插拔事件 (EVENT_CARD_CHG) 可能同时包含”插入”和”拔出”两种应用场景,需要确保两种情况都被处理。

5.2 shared_task_cnt 机制

数据结构:

1
2
3
4
5
typedef struct{
u8 status;
u32 id;
u8 shared_task_cnt; // 共享任务计数器
} win_task_t;

设置任务时递增计数:

1
2
3
4
5
static void win_set_task(task_mgr_t *mgr, e_task_t taskid, u8 status)
{
mgr->tasks[taskid].status = status;
mgr->tasks[taskid].shared_task_cnt++; // 共享任务计数 +1
}

处理任务时递减计数并重入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 处理 task 依次顺序执行,有优先级
for(u8 i = 0; i < os->task_mgr.task_cnt; ++i){
if(os->task_mgr.tasks[i].status == TASK_STATUS_OCCUR &&
os->task_mgr.tasks[i].shared_task_cnt != 0){
DbgInfo(MODULE_MAIN_THR, FEATURE_THREAD_TRACE, NOT_TO_RAM,
"task processing, task_id=%d\n", i);

os->task_mgr.tasks[i].status = TASK_STATUS_OCCUR; // 保持 OCCUR 状态
os->task_mgr.tasks[i].shared_task_cnt--; // 计数 -1

if(process_task(i, pdx, os))
goto exit;

/* CARD_CHANGE 包括两种应用情况:插入卡和拔出卡
* 如果同一事件中发生这两种情况,任务被两种情况共享
* 必须再次处理 CARD_CHANGE
*/
if(os->task_mgr.tasks[i].shared_task_cnt != 0)
i--; // 重新处理该任务

DbgInfo(MODULE_MAIN_THR, FEATURE_THREAD_TRACE, NOT_TO_RAM,
"task done, task_id=%d\n", i);
}
}

5.3 机制图解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
场景:卡在一次中断中被拔出又插入

中断处理:

os_set_task(TASK_CARD_CHG) → shared_task_cnt = 1

os_set_task(TASK_CARD_CHG) → shared_task_cnt = 2 (再次设置同一任务)

主循环处理:

第一次处理 TASK_CARD_CHG:
- shared_task_cnt: 2 → 1
- 处理完成后检查: cnt != 0, i-- 重新处理

第二次处理 TASK_CARD_CHG:
- shared_task_cnt: 1 → 0
- 处理完成后检查: cnt == 0, 不重入

6. 调试与问题排查

6.1 关键调试日志

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 事件设置
DbgInfo(MODULE_OS_API, FEATURE_THREAD_TRACE, NOT_TO_RAM,
"%s set evt %x\n", __FUNCTION__, event);

// 事件等待
DbgInfo(MODULE_OS_API, FEATURE_THREAD_TRACE, NOT_TO_RAM,
"%s wait evt done %x\n", __FUNCTION__, i);

// 事件处理
DbgInfo(MODULE_MAIN_THR, FEATURE_THREAD_TRACE, NOT_TO_RAM,
"Thr get Event=%d\n", evt);

// 任务处理
DbgInfo(MODULE_MAIN_THR, FEATURE_THREAD_TRACE, NOT_TO_RAM,
"task processing, task_id=%d\n", i);

6.2 常见问题

问题 可能原因 解决方案
事件不触发 StorPortIssueDpc 未正确调用 检查 win_get_evt 返回值
事件丢失 同一事件快速触发两次 启用 shared_task_cnt
线程死锁 在事件处理中调用 StorPortWaitForSingleObject 避免阻塞调用
CPU 100% os_wait_eventos_sleep 添加适当延迟

6.3 验证清单

  • 确认移除了所有 #ifdef MultiThread 分支
  • 确认所有 os_set_event 调用使用新签名
  • 确认 thread_main 使用 switch-case 而非 task manager
  • 确认 shared_task_cnt 正确处理共享事件
  • 确认没有调用禁止的 DDI 函数

7. 参考资料

7.1 Microsoft 官方文档

7.2 Git Commit 信息

1
2
3
4
5
6
7
8
commit 906a83c5bd7ae70f0cd2e9649c377d9931e335ab
Merge: f827ec2 e91fae5
Author: thomas.hu <thomas.hu@bayhubtech.com>
Date: Fri May 20 10:54:36 2022 +0800

merge multi-thread issue fix solution: use one event to handle multiple tasks.

Git Tag: gg8-master20220520 → storport_win11_20220428

7.3 相关文件

文件 改动说明
SDSTORDriver/sdstor/main/thread.c 主线程事件处理重构
SDSTORDriver/sdstor/windows_os/winapi.c 事件 API 简化
SDSTORDriver/sdstor/windows_os/winapi.h task 结构体修改

文档生成日期: 2026-03-20
版本: 1.0