Source code of Windows XP (NT5)
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

/*++
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