VfDeadlockReleaseResource
VOID __stdcall 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 *Param4;
ULONG_PTR v21;
_ETHREAD *v22;
_VI_DEADLOCK_NODE *CurrentSpinNode;
__int16 v24;
_DWORD *v25;
union {$ACDF71180F6620BE0295814E0676F670 __s0;unsigned int Whole;} v26;
_VI_DEADLOCK_NODE *CurrentOtherNode;
_VI_DEADLOCK_NODE *v28;
_VI_DEADLOCK_NODE *v29;
_VI_DEADLOCK_NODE *Parent;
unsigned int NodeCount;
_QWORD *v32;
_QWORD *v33;
UINT64 a7;
UINT64 a7a;
UINT8 OldIrql;
int v37;
VOID *NodesToFree;
_ETHREAD *v39;
VOID *BackTrace[8];
ThreadOwner = 0i64;
v39 = Thread;
v6 = Type;
NodesToFree = 0i64;
memset(BackTrace, 0i64, sizeof(BackTrace));
v37 = 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, &NodesToFree);
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( CurrentSpinNode->Root == Param3 )
{
CurrentSpinNode->u1.Whole &= ~1u;
v11 = CurrentSpinNode;
}
else
{
++v25[8208];
if( (ViDeadlockResourceTypeInfo[CurrentSpinNode->Root->Type] & 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,
CurrentSpinNode->Root->ResourceAddress,
ThreadOwner,
Resource);
ViDeadlockPreprocessOptions(
&qword_140C12D7C,
(CHAR *)"Releasing two locks in reverse order of their acquire.",
0x1003ui64,
(UINT64)Resource,
(UINT64)CurrentSpinNode->Root->ResourceAddress,
(UINT64)ThreadOwner,
a7a);
VfReportIssueWithOptions(
0xC4ui64,
0x1003u,
(ULONG_PTR)Resource,
(ULONG_PTR)CurrentSpinNode->Root->ResourceAddress,
(ULONG_PTR)ThreadOwner,
&qword_140C12D7C);
}
while( CurrentSpinNode->Root != Param3 )
{
CurrentSpinNode = CurrentSpinNode->Parent;
if( !CurrentSpinNode )
goto LABEL_42;
}
CurrentSpinNode->u1.Whole &= ~1u;
v11 = CurrentSpinNode;
v26.0 = ($ACDF71180F6620BE0295814E0676F670)CurrentSpinNode->u1;
if( (*(_BYTE *)&v26.0 & 4) == 0 )
{
++*((_DWORD *)ViDeadlockGlobals + 8209);
v26.0 = ($ACDF71180F6620BE0295814E0676F670)CurrentSpinNode->u1;
}
CurrentSpinNode->u1.Whole = v26.Whole | 4;
}
LABEL_42:
if( (unsigned int)(Param3->Type - 5) <= 1 )
{
v29 = ThreadOwner->CurrentSpinNode;
if( v29 )
{
do
{
if( (v29->u1.Whole & 1) != 0 && v29->ThreadEntry == ThreadOwner )
break;
Parent = v29->Parent;
ThreadOwner->CurrentSpinNode = v29->Parent;
v29 = Parent;
}
while( Parent );
}
}
else
{
CurrentOtherNode = ThreadOwner->CurrentOtherNode;
if( CurrentOtherNode )
{
do
{
if( (CurrentOtherNode->u1.Whole & 1) != 0 && CurrentOtherNode->ThreadEntry == ThreadOwner )
break;
v28 = CurrentOtherNode->Parent;
ThreadOwner->CurrentOtherNode = CurrentOtherNode->Parent;
CurrentOtherNode = v28;
}
while( v28 );
}
}
if( v11 )
{
v11->ThreadEntry = 0i64;
NodeCount = --ThreadOwner->NodeCount;
if( v22 != v39 )
{
v11->u1.Whole |= 4u;
NodeCount = ThreadOwner->NodeCount;
}
if( !NodeCount )
{
v37 = 1;
ViDeadlockRemoveThread(ThreadOwner, 0i64);
}
}
}
}
else if( !*((_DWORD *)ViDeadlockGlobals + 8196) && *((int *)ViDeadlockGlobals + 8282) <= 1024 )
{
Param4 = ViDeadlockSearchThread(&Thread->Tcb);
ViDeadlockPreprocessOptions(
&unk_140C12D78,
(CHAR *)"Releasing lock 0x%p that is not owned by the current thread.",
0x1007ui64,
(UINT64)Resource,
(UINT64)Param3,
(UINT64)Param4,
a7);
v21 = (unsigned int)ViDeadlockSearchThread(&Thread->Tcb);
VfReportIssueWithOptions(0xC4ui64, 0x1007u, (ULONG_PTR)Resource, (ULONG_PTR)Param3, v21, &unk_140C12D78);
}
goto LABEL_57;
}
ViDeadlockPreprocessOptions(
(UINT64 *)((char *)&qword_140C12D70 + 4),
(CHAR *)"Releasing lock 0x%p using mismatched API for this lock type.",
0x1009ui64,
(UINT64)Resource,
v18,
v6,
a7);
VfReportIssueWithOptions(
0xC4ui64,
0x1009u,
(ULONG_PTR)Resource,
Param3->Type,
v6,
(UINT64 *)((char *)&qword_140C12D70 + 4));
LABEL_57:
*(_OWORD *)Param3->LastReleaseTrace = *(_OWORD *)BackTrace;
*(_OWORD *)&Param3->LastReleaseTrace[2] = *(_OWORD *)&BackTrace[2];
*(_OWORD *)&Param3->LastReleaseTrace[4] = *(_OWORD *)&BackTrace[4];
*(_OWORD *)&Param3->LastReleaseTrace[6] = *(_OWORD *)&BackTrace[6];
v9 = v37;
}
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 = NodesToFree;
if( NodesToFree )
{
do
{
v33 = (_QWORD *)*v32;
ViDeadlockFree(v32, ViDeadlockNode);
v32 = v33;
}
while( v33 );
}
if( v9 )
ViDeadlockFree(ThreadOwner, ViDeadlockThread);
}Referenced by:
VerifierExReleaseFastMutex
VerifierExReleaseFastMutexUnsafe
VerifierKeReleaseInStackQueuedSpinLock
VerifierKeReleaseInStackQueuedSpinLockForDpc
VerifierKeReleaseInStackQueuedSpinLockFromDpcLevel
VerifierKeReleaseMutant
VerifierKeReleaseMutex
VerifierKeReleaseSpinLock
VerifierKeReleaseSpinLockFromDpcLevel