VfDeadlockReleaseResource
VOID __fastcall VfDeadlockReleaseResource(
VOID *Resource,
_VI_DEADLOCK_RESOURCE_TYPE Type,
_ETHREAD *Thread,
VOID *Caller){
_VI_DEADLOCK_THREAD *ThreadOwner;
UINT64 v6;
int v9;
_VI_DEADLOCK_RESOURCE_TYPE v10;
_VI_DEADLOCK_NODE *v11;
unsigned int v12;
VOID *v13;
__int64 v14;
volatile unsigned __int64 TickCountQuad;
_VI_DEADLOCK_RESOURCE *v16;
_VI_DEADLOCK_RESOURCE *Param3;
UINT64 v18;
__int16 v19;
_VI_DEADLOCK_THREAD *v20;
_VI_DEADLOCK_THREAD *v21;
_ETHREAD *v22;
_VI_DEADLOCK_NODE *CurrentSpinNode;
__int16 v24;
_DWORD *v25;
int v26;
_VI_DEADLOCK_NODE *CurrentOtherNode;
_VI_DEADLOCK_NODE *v28;
_VI_DEADLOCK_NODE *v29;
_VI_DEADLOCK_NODE *v30;
unsigned int NodeCount;
_QWORD *v32;
_QWORD *v33;
UINT8 OldIrql;
int v35;
PVOID Entry;
_ETHREAD *v37;
PVOID BackTrace[2];
__int128 v39;
__int128 v40;
__int128 v41;
ThreadOwner = 0i64;
v37 = Thread;
v6 = Type;
Entry = 0i64;
memset((INT64)BackTrace, 0i64);
v35 = 0;
v9 = 0;
if( !(unsigned int)ViDeadlockCanProceed(Resource, v10)
|| (unsigned int)ViIsThreadInsidePagingCodePaths()
|| *((_DWORD *)ViDeadlockGlobals + 8196)
|| *((int *)ViDeadlockGlobals + 8282) > 1024 )
{
return;
}
v11 = 0i64;
v12 = RtlCaptureStackBackTrace(2ui64, 8ui64, BackTrace, 0i64);
v13 = BackTrace[0];
if( !v12 )
v13 = Caller;
BackTrace[0] = v13;
v14 = 1i64;
if( v12 )
v14 = v12;
if( (unsigned int)v14 < 8 )
BackTrace[v14] = 0i64;
OldIrql = ViRaiseIrqlToDpcLevel();
ViDeadlockDetectionLock(1ui64);
TickCountQuad = KUSER_SHARED_DATA.TickCountQuad;
if( ViDeadlockDetectionEnabled )
{
v16 = ViDeadlockSearchResource(Resource, &Entry);
Param3 = v16;
if( !v16 )
{
v9 = 0;
goto LABEL_59;
}
v18 = v16->Type;
if( (_DWORD)v18 == (_DWORD)v6 )
goto LABEL_17;
if( (_DWORD)v18 == 7 )
{
if( (unsigned int)(v6 - 5) <= 1 )
{
Param3->Type = v6;
LODWORD(v18) = v6;
goto LABEL_17;
}
}
else if( (_DWORD)v18 == 1 && (_DWORD)v6 == 2 )
{
if( *((_WORD *)Param3 + 3) > 1u )
*((_WORD *)Param3 + 3) = 1;
LODWORD(v18) = 1;
LABEL_17:
v19 = *((_WORD *)Param3 + 3);
if( v19 )
{
ThreadOwner = Param3->ThreadOwner;
v22 = ThreadOwner->Thread;
if( (unsigned int)(v18 - 5) <= 1 )
CurrentSpinNode = ThreadOwner->CurrentSpinNode;
else
CurrentSpinNode = ThreadOwner->CurrentOtherNode;
v24 = v19 - 1;
*((_WORD *)Param3 + 3) = v24;
if( !v24 )
{
v25 = ViDeadlockGlobals;
Param3->ThreadOwner = 0i64;
++v25[8210];
if( *((_VI_DEADLOCK_RESOURCE **)CurrentSpinNode + 7) == Param3 )
{
*((_DWORD *)CurrentSpinNode + 18) &= ~1u;
v11 = CurrentSpinNode;
}
else
{
++v25[8208];
if( (ViDeadlockResourceTypeInfo[**((int **)CurrentSpinNode + 7)] & 4) == 0
&& (ViDeadlockResourceTypeInfo[Param3->Type] & 4) == 0 )
{
DbgPrintEx(0x5Du, 0, "Deadlock detection: Must release resources in reverse-order\n");
DbgPrintEx(
0x5Du,
0,
"Resource %p acquired before resource %p -- \nCurrent thread(%p) is trying to release %p first\n",
Resource,
*(const void **)(*((_QWORD *)CurrentSpinNode + 7) + 8i64),
ThreadOwner,
Resource);
ViDeadlockPreprocessOptions(
&dword_140C12D7C,
"Releasing two locks in reverse order of their acquire.",
0x1003ui64,
(UINT64)Resource,
*(_QWORD *)(*((_QWORD *)CurrentSpinNode + 7) + 8i64),
(UINT64)ThreadOwner);
VfReportIssueWithOptions(
0xC4ui64,
0x1003ui64,
(UINT64)Resource,
*(_QWORD *)(*((_QWORD *)CurrentSpinNode + 7) + 8i64),
(UINT64)ThreadOwner,
&dword_140C12D7C);
}
while( *((_VI_DEADLOCK_RESOURCE **)CurrentSpinNode + 7) != Param3 )
{
CurrentSpinNode = *(_VI_DEADLOCK_NODE **)CurrentSpinNode;
if( !CurrentSpinNode )
goto LABEL_42;
}
*((_DWORD *)CurrentSpinNode + 18) &= ~1u;
v11 = CurrentSpinNode;
v26 = *((_DWORD *)CurrentSpinNode + 18);
if( (v26 & 4) == 0 )
{
++*((_DWORD *)ViDeadlockGlobals + 8209);
v26 = *((_DWORD *)CurrentSpinNode + 18);
}
*((_DWORD *)CurrentSpinNode + 18) = v26 | 4;
}
LABEL_42:
if( (unsigned int)(Param3->Type - 5) <= 1 )
{
v29 = ThreadOwner->CurrentSpinNode;
if( v29 )
{
do
{
if( (*((_DWORD *)v29 + 18) & 1) != 0 && *((_VI_DEADLOCK_THREAD **)v29 + 8) == ThreadOwner )
break;
v30 = *(_VI_DEADLOCK_NODE **)v29;
ThreadOwner->CurrentSpinNode = *(_VI_DEADLOCK_NODE **)v29;
v29 = v30;
}
while( v30 );
}
}
else
{
CurrentOtherNode = ThreadOwner->CurrentOtherNode;
if( CurrentOtherNode )
{
do
{
if( (*((_DWORD *)CurrentOtherNode + 18) & 1) != 0
&& *((_VI_DEADLOCK_THREAD **)CurrentOtherNode + 8) == ThreadOwner )
{
break;
}
v28 = *(_VI_DEADLOCK_NODE **)CurrentOtherNode;
ThreadOwner->CurrentOtherNode = *(_VI_DEADLOCK_NODE **)CurrentOtherNode;
CurrentOtherNode = v28;
}
while( v28 );
}
}
if( v11 )
{
*((_QWORD *)v11 + 8) = 0i64;
NodeCount = --ThreadOwner->NodeCount;
if( v22 != v37 )
{
*((_DWORD *)v11 + 18) |= 4u;
NodeCount = ThreadOwner->NodeCount;
}
if( !NodeCount )
{
v35 = 1;
ViDeadlockRemoveThread(ThreadOwner, 0i64);
}
}
}
}
else if( !*((_DWORD *)ViDeadlockGlobals + 8196) && *((int *)ViDeadlockGlobals + 8282) <= 1024 )
{
v20 = ViDeadlockSearchThread((_KTHREAD *)Thread);
ViDeadlockPreprocessOptions(
&byte_140C12D78,
"Releasing lock 0x%p that is not owned by the current thread.",
0x1007ui64,
(UINT64)Resource,
(UINT64)Param3,
(UINT64)v20);
v21 = ViDeadlockSearchThread((_KTHREAD *)Thread);
VfReportIssueWithOptions(0xC4ui64, 0x1007ui64, (UINT64)Resource, (UINT64)Param3, (UINT64)v21, &byte_140C12D78);
}
goto LABEL_57;
}
ViDeadlockPreprocessOptions(
&dword_140C12D74,
"Releasing lock 0x%p using mismatched API for this lock type.",
0x1009ui64,
(UINT64)Resource,
v18,
v6);
VfReportIssueWithOptions(0xC4ui64, 0x1009ui64, (UINT64)Resource, Param3->Type, v6, &dword_140C12D74);
LABEL_57:
*(_OWORD *)Param3->LastReleaseTrace = *(_OWORD *)BackTrace;
*(_OWORD *)&Param3->LastReleaseTrace[2] = v39;
*(_OWORD *)&Param3->LastReleaseTrace[4] = v40;
*(_OWORD *)&Param3->LastReleaseTrace[6] = v41;
v9 = v35;
}
LABEL_59:
if( (signed __int64)(KUSER_SHARED_DATA.TickCountQuad - TickCountQuad) > *((_QWORD *)ViDeadlockGlobals + 1) )
*((_QWORD *)ViDeadlockGlobals + 1) = KUSER_SHARED_DATA.TickCountQuad - TickCountQuad;
ViDeadlockDetectionUnlock(1ui64);
ViLowerIrql(OldIrql);
v32 = Entry;
if( Entry )
{
do
{
v33 = (_QWORD *)*v32;
ViDeadlockFree(v32, 2);
v32 = v33;
}
while( v33 );
}
if( v9 )
ViDeadlockFree(ThreadOwner, 3);
}Referenced by:
VerifierExReleaseFastMutex
VerifierExReleaseFastMutexUnsafe
VerifierKeReleaseInStackQueuedSpinLock
VerifierKeReleaseInStackQueuedSpinLockForDpc
VerifierKeReleaseInStackQueuedSpinLockFromDpcLevel
VerifierKeReleaseMutant
VerifierKeReleaseMutex
VerifierKeReleaseSpinLock
VerifierKeReleaseSpinLockFromDpcLevel