mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
315 lines
8.0 KiB
315 lines
8.0 KiB
/*++
|
|
|
|
Copyright (c) 2001-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ownerref.cxx
|
|
|
|
Abstract:
|
|
|
|
This module implements a reference count tracing facility.
|
|
|
|
Author:
|
|
|
|
Keith Moore (keithmo) 10-Jun-1998
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "precomp.h"
|
|
|
|
|
|
// Globals
|
|
LIST_ENTRY g_OwnerRefTraceLogGlobalListHead;
|
|
UL_SPIN_LOCK g_OwnerRefTraceLogGlobalSpinLock;
|
|
LONG g_OwnerRefTraceLogGlobalCount;
|
|
|
|
|
|
VOID
|
|
UlInitializeOwnerRefTraceLog(
|
|
VOID)
|
|
{
|
|
InitializeListHead(&g_OwnerRefTraceLogGlobalListHead);
|
|
UlInitializeSpinLock( &g_OwnerRefTraceLogGlobalSpinLock,
|
|
"OwnerRefTraceLogGlobal" );
|
|
g_OwnerRefTraceLogGlobalCount = 0;
|
|
} // UlInitializeOwnerRefTraceLog
|
|
|
|
|
|
VOID
|
|
UlTerminateOwnerRefTraceLog(
|
|
VOID)
|
|
{
|
|
ASSERT( IsListEmpty(&g_OwnerRefTraceLogGlobalListHead) );
|
|
ASSERT( 0 == g_OwnerRefTraceLogGlobalCount );
|
|
} // UlTerminateOwnerRefTraceLog
|
|
|
|
|
|
|
|
#if ENABLE_OWNER_REF_TRACE
|
|
|
|
POWNER_REF_TRACELOG
|
|
CreateOwnerRefTraceLog(
|
|
IN ULONG LogSize,
|
|
IN ULONG ExtraBytesInHeader
|
|
)
|
|
{
|
|
POWNER_REF_TRACELOG pOwnerRefTraceLog = NULL;
|
|
|
|
PTRACE_LOG pTraceLog
|
|
= CreateTraceLog(
|
|
OWNER_REF_TRACELOG_SIGNATURE,
|
|
LogSize,
|
|
sizeof(OWNER_REF_TRACELOG)
|
|
- FIELD_OFFSET(OWNER_REF_TRACELOG, OwnerHeader)
|
|
+ ExtraBytesInHeader,
|
|
sizeof(OWNER_REF_TRACE_LOG_ENTRY)
|
|
);
|
|
|
|
if (pTraceLog != NULL)
|
|
{
|
|
pOwnerRefTraceLog = (POWNER_REF_TRACELOG) pTraceLog;
|
|
|
|
ASSERT(pOwnerRefTraceLog->TraceLog.TypeSignature
|
|
== OWNER_REF_TRACELOG_SIGNATURE);
|
|
|
|
InitializeListHead(&pOwnerRefTraceLog->OwnerHeader.ListHead);
|
|
UlInitializeSpinLock( &pOwnerRefTraceLog->OwnerHeader.SpinLock,
|
|
"OwnerRefTraceLog" );
|
|
pOwnerRefTraceLog->OwnerHeader.MonotonicId = 0;
|
|
pOwnerRefTraceLog->OwnerHeader.OwnersCount = 0;
|
|
|
|
// insert into global list
|
|
|
|
ExInterlockedInsertTailList(
|
|
&g_OwnerRefTraceLogGlobalListHead,
|
|
&pOwnerRefTraceLog->OwnerHeader.GlobalListEntry,
|
|
KSPIN_LOCK_FROM_UL_SPIN_LOCK(&g_OwnerRefTraceLogGlobalSpinLock)
|
|
);
|
|
|
|
InterlockedIncrement(&g_OwnerRefTraceLogGlobalCount);
|
|
}
|
|
|
|
return pOwnerRefTraceLog;
|
|
} // CreateOwnerRefTraceLog
|
|
|
|
|
|
PREF_OWNER
|
|
NewRefOwner(
|
|
POWNER_REF_TRACELOG pOwnerRefTraceLog,
|
|
PVOID pOwner,
|
|
IN PPREF_OWNER ppRefOwner,
|
|
IN ULONG OwnerSignature
|
|
)
|
|
{
|
|
PREF_OWNER pRefOwner;
|
|
|
|
ASSERT( UlDbgSpinLockOwned( &pOwnerRefTraceLog->OwnerHeader.SpinLock ) );
|
|
|
|
pRefOwner = UL_ALLOCATE_STRUCT(
|
|
NonPagedPool,
|
|
REF_OWNER,
|
|
UL_OWNER_REF_POOL_TAG
|
|
);
|
|
|
|
if (pRefOwner != NULL)
|
|
{
|
|
int i;
|
|
|
|
pRefOwner->Signature = OWNER_REF_SIGNATURE;
|
|
pRefOwner->OwnerSignature = OwnerSignature;
|
|
|
|
InsertTailList(
|
|
&pOwnerRefTraceLog->OwnerHeader.ListHead,
|
|
&pRefOwner->ListEntry
|
|
);
|
|
|
|
++pOwnerRefTraceLog->OwnerHeader.OwnersCount;
|
|
|
|
pRefOwner->pOwner = pOwner;
|
|
pRefOwner->pOwnerRefTraceLog = pOwnerRefTraceLog;
|
|
pRefOwner->RelativeRefCount = 0;
|
|
pRefOwner->OwnedNextEntry = -1;
|
|
|
|
for (i = 0; i < OWNED_REF_NUM_ENTRIES; ++i)
|
|
{
|
|
pRefOwner->RecentEntries[i].RefIndex = -1;
|
|
pRefOwner->RecentEntries[i].MonotonicId = -1;
|
|
pRefOwner->RecentEntries[i].Action = -1;
|
|
}
|
|
|
|
*ppRefOwner = pRefOwner;
|
|
}
|
|
|
|
return pRefOwner;
|
|
} // NewRefOwner
|
|
|
|
|
|
VOID
|
|
InsertRefOwner(
|
|
IN POWNER_REF_TRACELOG pOwnerRefTraceLog,
|
|
IN PVOID pOwner,
|
|
IN PPREF_OWNER ppRefOwner,
|
|
IN ULONG OwnerSignature,
|
|
IN LONGLONG RefIndex,
|
|
IN LONG MonotonicId,
|
|
IN LONG IncrementValue,
|
|
IN USHORT Action
|
|
)
|
|
{
|
|
PREF_OWNER pRefOwner = NULL;
|
|
KIRQL OldIrql;
|
|
|
|
ASSERT(RefIndex >= 0);
|
|
|
|
UlAcquireSpinLock(&pOwnerRefTraceLog->OwnerHeader.SpinLock, &OldIrql);
|
|
|
|
pRefOwner = *ppRefOwner;
|
|
|
|
if (pRefOwner == NULL)
|
|
{
|
|
pRefOwner = NewRefOwner(
|
|
pOwnerRefTraceLog,
|
|
pOwner,
|
|
ppRefOwner,
|
|
OwnerSignature
|
|
);
|
|
}
|
|
|
|
if (pRefOwner != NULL)
|
|
{
|
|
ULONG Index;
|
|
|
|
ASSERT(pRefOwner->Signature == OWNER_REF_SIGNATURE);
|
|
ASSERT(pRefOwner->pOwner == pOwner);
|
|
ASSERT(pRefOwner->OwnerSignature == OwnerSignature);
|
|
ASSERT(pRefOwner->pOwnerRefTraceLog == pOwnerRefTraceLog);
|
|
|
|
Index = ((ULONG) ++pRefOwner->OwnedNextEntry) % OWNED_REF_NUM_ENTRIES;
|
|
|
|
pRefOwner->RecentEntries[Index].RefIndex = RefIndex;
|
|
pRefOwner->RecentEntries[Index].MonotonicId = MonotonicId;
|
|
pRefOwner->RecentEntries[Index].Action = Action;
|
|
|
|
if (IncrementValue > 0)
|
|
++pRefOwner->RelativeRefCount;
|
|
else if (IncrementValue < 0)
|
|
--pRefOwner->RelativeRefCount;
|
|
// else do nothing if IncrementValue == 0.
|
|
|
|
ASSERT(pRefOwner->RelativeRefCount >= 0);
|
|
}
|
|
|
|
UlReleaseSpinLock(&pOwnerRefTraceLog->OwnerHeader.SpinLock, OldIrql);
|
|
|
|
} // InsertRefOwner
|
|
|
|
|
|
LONGLONG
|
|
WriteOwnerRefTraceLog(
|
|
IN POWNER_REF_TRACELOG pOwnerRefTraceLog,
|
|
IN PVOID pOwner,
|
|
IN PPREF_OWNER ppRefOwner,
|
|
IN ULONG OwnerSignature,
|
|
IN USHORT Action,
|
|
IN LONG NewRefCount,
|
|
IN LONG MonotonicId,
|
|
IN LONG IncrementValue,
|
|
IN PVOID pFileName,
|
|
IN USHORT LineNumber
|
|
)
|
|
{
|
|
OWNER_REF_TRACE_LOG_ENTRY entry;
|
|
LONGLONG RefIndex;
|
|
|
|
ASSERT(NULL != ppRefOwner);
|
|
ASSERT(Action < (1 << REF_TRACE_ACTION_BITS));
|
|
|
|
if (NULL == pOwnerRefTraceLog)
|
|
return -1;
|
|
|
|
entry.NewRefCount = NewRefCount;
|
|
entry.pOwner = pOwner;
|
|
entry.pFileName = pFileName;
|
|
entry.LineNumber = LineNumber;
|
|
entry.Action = Action;
|
|
|
|
RefIndex = WriteTraceLog( &pOwnerRefTraceLog->TraceLog, &entry );
|
|
|
|
InsertRefOwner(
|
|
pOwnerRefTraceLog,
|
|
pOwner,
|
|
ppRefOwner,
|
|
OwnerSignature,
|
|
RefIndex,
|
|
MonotonicId,
|
|
IncrementValue,
|
|
Action
|
|
);
|
|
|
|
return RefIndex;
|
|
} // WriteOwnerRefTraceLog
|
|
|
|
|
|
VOID
|
|
DestroyOwnerRefTraceLog(
|
|
IN POWNER_REF_TRACELOG pOwnerRefTraceLog
|
|
)
|
|
{
|
|
if (pOwnerRefTraceLog != NULL)
|
|
{
|
|
KIRQL OldIrql;
|
|
PLIST_ENTRY pEntry;
|
|
int i = 0;
|
|
|
|
UlAcquireSpinLock(&pOwnerRefTraceLog->OwnerHeader.SpinLock, &OldIrql);
|
|
|
|
for (pEntry = pOwnerRefTraceLog->OwnerHeader.ListHead.Flink;
|
|
pEntry != &pOwnerRefTraceLog->OwnerHeader.ListHead;
|
|
++i)
|
|
{
|
|
PREF_OWNER pRefOwner =
|
|
CONTAINING_RECORD(pEntry, REF_OWNER, ListEntry);
|
|
|
|
pEntry = pEntry->Flink; // save before deletion
|
|
|
|
ASSERT(pRefOwner->Signature == OWNER_REF_SIGNATURE);
|
|
ASSERT(pRefOwner->RelativeRefCount == 0);
|
|
|
|
UL_FREE_POOL_WITH_SIG(pRefOwner, UL_OWNER_REF_POOL_TAG);
|
|
}
|
|
|
|
UlReleaseSpinLock(&pOwnerRefTraceLog->OwnerHeader.SpinLock, OldIrql);
|
|
|
|
ASSERT(i == pOwnerRefTraceLog->OwnerHeader.OwnersCount);
|
|
|
|
// Remove log from global list
|
|
|
|
UlAcquireSpinLock(&g_OwnerRefTraceLogGlobalSpinLock, &OldIrql);
|
|
RemoveEntryList(&pOwnerRefTraceLog->OwnerHeader.GlobalListEntry);
|
|
UlReleaseSpinLock(&g_OwnerRefTraceLogGlobalSpinLock, OldIrql);
|
|
InterlockedDecrement(&g_OwnerRefTraceLogGlobalCount);
|
|
|
|
DestroyTraceLog( (PTRACE_LOG) pOwnerRefTraceLog );
|
|
}
|
|
} // DestroyOwnerRefTraceLog
|
|
|
|
|
|
|
|
VOID
|
|
ResetOwnerRefTraceLog(
|
|
IN POWNER_REF_TRACELOG pOwnerRefTraceLog
|
|
)
|
|
{
|
|
// CODEWORK: reset OwnerHeader?
|
|
if (pOwnerRefTraceLog != NULL)
|
|
{
|
|
ResetTraceLog(&pOwnerRefTraceLog->TraceLog);
|
|
}
|
|
} // ResetOwnerRefTraceLog
|
|
|
|
#endif // ENABLE_OWNER_REF_TRACE
|
|
|