首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >修复IRQL级别警告的预快注释

修复IRQL级别警告的预快注释
EN

Stack Overflow用户
提问于 2016-05-17 02:36:45
回答 1查看 835关注 0票数 6

我正在为windows 7 32位编写设备驱动程序。我正在使用WDK版本7600.16385.1。到目前为止一切都进行得很顺利,但prefast一直告诉我,我正在搞砸IRQL的水平。特别是当我试图锁定/解锁共享缓冲区时。

我有一个表示如下缓冲区的结构:

代码语言:javascript
复制
typedef struct _PORT_BUFFER {

    WDFMEMORY   mMemory;
    PUCHAR      pucBuff;
    ULONG       ulSizeMax;
    ULONG       ulSizeCurr;
    ULONG       ulAdd;
    ULONG       ulRemove;
    ULONG       ulLost;
    WDFREQUEST  rPending;
    BOOLEAN     bDMAing;

    WDFSPINLOCK slLock;

} PORT_BUFFER, *PPORT_BUFFER;

我有两个功能可以锁定和解锁所述缓冲区:

代码语言:javascript
复制
VOID PLxBufferLock(PPORT_BUFFER ppbBuff){

    WdfSpinLockAcquire(ppbBuff->slLock);

}

VOID PLxBufferUnlock(PPORT_BUFFER ppbBuff){

    WdfSpinLockRelease(ppbBuff->slLock);

}

当我编译我的驱动程序时,prefast告诉我:

代码语言:javascript
复制
warning 28167 : The function 'PLxBufferLock' changes the IRQL and does not restore the IRQL before it exits. It should be annotated to reflect the change or the IRQL should be restored. IRQL was last set to 2 at line 57.

warning 28167 : The function 'PLxBufferUnlock' changes the IRQL and does not restore the IRQL before it exits. It should be annotated to reflect the change or the IRQL should be restored. IRQL was last set at line 63.

因此,我查看了WdfSpinLockAcquire和WdfSpinLockRelease是如何定义的:

代码语言:javascript
复制
__drv_raisesIRQL(DISPATCH_LEVEL)
__drv_maxIRQL(DISPATCH_LEVEL)
VOID
FORCEINLINE
WdfSpinLockAcquire(
    __in
    __drv_savesIRQL
    __drv_neverHold(SpinLockObj)
    __drv_acquiresResource(SpinLockObj)
    WDFSPINLOCK SpinLock
    )
{
    ((PFN_WDFSPINLOCKACQUIRE) WdfFunctions[WdfSpinLockAcquireTableIndex])(WdfDriverGlobals, SpinLock);
}

__drv_maxIRQL(DISPATCH_LEVEL)
__drv_minIRQL(DISPATCH_LEVEL)
VOID
FORCEINLINE
WdfSpinLockRelease(
    __in
    __drv_restoresIRQL
    __drv_mustHold(SpinLockObj)
    __drv_releasesResource(SpinLockObj)
    WDFSPINLOCK SpinLock
    )
{
    ((PFN_WDFSPINLOCKRELEASE) WdfFunctions[WdfSpinLockReleaseTableIndex])(WdfDriverGlobals, SpinLock);
}

看起来很直截了当。因此,我改变了我的功能,使之看起来是一样的:

代码语言:javascript
复制
__drv_raisesIRQL(DISPATCH_LEVEL)
__drv_maxIRQL(DISPATCH_LEVEL)
VOID PLxBufferLock(
    __in
    __drv_savesIRQL
    __drv_neverHold(ppbBuff)
    __drv_acquiresResource(ppbBuff)
    PPORT_BUFFER ppbBuff);

__drv_maxIRQL(DISPATCH_LEVEL)
__drv_minIRQL(DISPATCH_LEVEL)
VOID PLxBufferUnlock(
    __in
    __drv_restoresIRQL
    __drv_mustHold(ppbBuff)
    __drv_releasesResource(ppbBuff)
    PPORT_BUFFER ppbBuff);

然后,我从两个警告转到许多关于泄漏ppbBuff的警告,但仍然没有正确地恢复IRQL级别:

代码语言:javascript
复制
warning 28103 : Leaking the ppbBuff stored in 'ppbBuff'.
warning 28104 : The ppbBuff that should have been acquired before function exit was not acquired.
warning 28107 : The ppbBuff '&pdepPort->pbRead' must be held when calling 'PLxBufferUnlock'.
warning 28107 : The ppbBuff '&pdepPort->pbWrite' must be held when calling 'PLxBufferUnlock'.
warning 28107 : The ppbBuff '&pdepExtPort->pbRead' must be held when calling 'PLxBufferUnlock'.
warning 28107 : The ppbBuff '&pdepExtPort->pbRead' must be held when calling 'PLxBufferUnlock'.
warning 28107 : The ppbBuff '&pdepExtPort->pbWrite' must be held when calling 'PLxBufferUnlock'.
warning 28157 : The IRQL in 'ppbBuff' was never restored.
warning 28158 : No IRQL was saved into 'ppbBuff'.
warning 28166 : The function 'PLxInitEvtPortCleanup' does not restore the IRQL to the value that was current at function entry and is required to do so. IRQL was last set at line 320.
warning 28166 : The function 'PLxReadEvt' does not restore the IRQL to the value that was current at function entry and is required to do so. IRQL was last set at line 51.
warning 28166 : The function 'PLxReadEvtTimer' does not restore the IRQL to the value that was current at function entry and is required to do so. IRQL was last set at line 104.
warning 28166 : The function 'PLxWriteEvt' does not restore the IRQL to the value that was current at function entry and is required to do so. IRQL was last set at line 60.

我使用缓冲区,我没有检查任何地方的错误,所以我认为我的锁定是正确的。有人知道在这种情况下该怎么安抚吗?谢谢!

编辑:

下面是一个使用锁定函数的示例:

代码语言:javascript
复制
VOID PLxInitEvtPortCleanup(WDFFILEOBJECT foFileObject){

    PDEVICE_EXTENSION_PORT  pdepPort = NULL;
    PDEVICE_EXTENSION_CARD  pdecCard = NULL;
    GSCSIO4BXSYNC_PORT_CONFIGURATION pcPortConfig = { 0 };
    WDFREQUEST rRequest = NULL;

    pdepPort = PLxGetDeviceContextPort(WdfFileObjectGetDevice(foFileObject));

    pdecCard = PLxGetDeviceContextCard(pdepPort->dDeviceCard);

    pcPortConfig.bEnable = FALSE;
    pcPortConfig.bRxEnable = FALSE;
    pcPortConfig.bTxEnable = FALSE;
    pcPortConfig.ulClockFrequency = 0;
    pcPortConfig.eptcdTxClockDirection = GSCSIO4BXSYNC_ESTCD_INPUT;

    PLxSioConfigPortSet(pdecCard,pdepPort->ulPortNumber,&pcPortConfig);

    PLxBufferLock(&pdepPort->pbRead);

    rRequest = PLxBufferClearPendingRequest(&pdepPort->pbRead);

    PLxBufferUnlock(&pdepPort->pbRead);

    if (rRequest) WdfRequestComplete(rRequest,STATUS_CANCELLED);

    PLxBufferLock(&pdepPort->pbWrite);

    rRequest = PLxBufferClearPendingRequest(&pdepPort->pbWrite);

    PLxBufferUnlock(&pdepPort->pbWrite);

    if (rRequest) WdfRequestComplete(rRequest,STATUS_CANCELLED);

}

我锁定缓冲区,删除任何挂起的请求,打开缓冲区并完成请求。Prefast告诉我,我没有正确地恢复IRQL级别。当我注释掉锁/清除/解锁/完成代码时,prefast又很高兴了。

编辑:

我已经升级到VS2015和WDK10+SDK10了。我添加了M‘建议的注释:

代码语言:javascript
复制
_Acquires_lock_(ppbBuff->slLock)
_Requires_lock_not_held_(ppbBuff->slLock)
_IRQL_saves_
VOID PLxBufferLock(PPORT_BUFFER ppbBuff){

    WdfSpinLockAcquire(ppbBuff->slLock);

}

_Releases_lock_(ppbBuff->slLock)
_Requires_lock_held_(ppbBuff->slLock)
_IRQL_restores_
VOID PLxBufferUnlock(PPORT_BUFFER ppbBuff){

    WdfSpinLockRelease(ppbBuff->slLock);

}

现在我得到了以下信息:

代码语言:javascript
复制
warning C28158: No IRQL was saved into 'return'.
warning C28167: The function 'PLxBufferLock' changes the IRQL and does not restore the IRQL before it exits. It should be annotated to reflect the change or the IRQL should be restored.
warning C28157: The IRQL in 'return' was never restored.

我注意到_Acquires_lock_和_Requires_lock_not_held_中定义为nothing,因此我查看了它们,并注意到它们需要定义_PREFAST_才能工作。因此,我将_PREFAST_添加到预处理器定义中。现在我得到了一堆链接错误,但没有更多的预快错误!

代码语言:javascript
复制
error LNK2005: __Lock_kind_mutex_ already defined in Buffer.obj
error LNK2005: __Lock_kind_event_ already defined in Buffer.obj
error LNK2005: __Lock_kind_semaphore_ already defined in Buffer.obj
error LNK2005: __Lock_kind_spin_lock_ already defined in Buffer.obj
error LNK2005: __Lock_kind_critical_section_ already defined in Buffer.obj
error LNK2001: unresolved external symbol __Prefast_unreferenced_parameter_impl_

当我把我的项目转换成VS2015时,我想我搞砸了一些事情。因此,我创建了标准的KMDF驱动程序项目,为您提供了一个很好的框架以供构建。我打开了新项目中的静态分析,并像以前一样定义了_PREFAST_,它也给出了相同的链接错误。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-05-17 03:49:53

你走上了一条好路。实际上,您可以提前告诉您的函数锁定或解锁对象,这要归功于SAL注释:注释锁定行为

您还需要提前告知IRQL的更改:驱动程序的IRQL注释

下面是使用基于代码的SAL注释的示例代码,它们可能与旧的WDK7不同:

代码语言:javascript
复制
_IRQL_raises_(DISPATCH_LEVEL)
_Acquires_lock_(ppbBuff->slLock)  
_Requires_lock_not_held_(ppbBuff->slLock)
VOID PLxBufferLock(_In_ _IRQL_saves_ PPORT_BUFFER ppbBuff){
        WdfSpinLockAcquire(ppbBuff->slLock);    
}

_Releases_lock_(ppbBuff->slLock)
_Requires_lock_held_(ppbBuff->slLock)
VOID PLxBufferUnlock(_In_ _IRQL_restores_ PPORT_BUFFER ppbBuff){
    WdfSpinLockRelease(ppbBuff->slLock);
}

备注:您应该对ppbBuff->slLock变量使用注释,而不是对其所有者使用注释。

更新:在阅读了上面的文档后,使用了更新注释,_IRQL_saves_/_IRQL_restores_必须对函数参数使用,而不是对函数。您还可能需要使用_IRQL_raises_。我已经编辑了上面的代码示例。还可以删除_PREFAST_定义以避免链接问题。_PREFAST_是由编译器在开始分析时定义的。

更新2:,而不是对_In_参数使用_IRQL_saves_/_IRQL_restores注释,您也可以对函数使用_IRQL_saves_global_(kind, param) / _IRQL_restores_global_(kind, param)注释。下面是一个更新的代码示例:

代码语言:javascript
复制
_IRQL_raises_(DISPATCH_LEVEL)
_Acquires_lock_(ppbBuff->slLock)  
_Requires_lock_not_held_(ppbBuff->slLock)
_IRQL_saves_global_(SpinLock, ppbBuff)
VOID PLxBufferLock(_In_ PPORT_BUFFER ppbBuff){
        WdfSpinLockAcquire(ppbBuff->slLock);    
}

_Releases_lock_(ppbBuff->slLock)
_Requires_lock_held_(ppbBuff->slLock)
_IRQL_restores_global_(SpinLock, ppbBuff)
VOID PLxBufferUnlock(_In_ PPORT_BUFFER ppbBuff){
    WdfSpinLockRelease(ppbBuff->slLock);
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37266215

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档