|
|
/*++
Copyright (c) 1998 Microsoft Corporation
Module Name: refcnt.c
Abstract: This module contains checked reference counting support functions. The free versions are inline. Author: Scott Holden (sholden) 12/29/1998 Borrowed from IrDA. Revision History:
--*/
#ifdef NDIS40 // Only used for NDIS40 code now.
#if DBG
//
// Include Files
//
#include "dlc.h"
#include "llc.h"
#include "dbgmsg.h"
#define EXPAND_TAG(_Tag) ((CHAR *)(&_Tag))[0], \
((CHAR *)(&_Tag))[1], \ ((CHAR *)(&_Tag))[2], \ ((CHAR *)(&_Tag))[3]
VOID ReferenceInitDbg( IN PREF_CNT pRefCnt, PVOID InstanceHandle, VOID (*DeleteHandler)(PVOID pvContext), ULONG TypeTag )
/*++
Routine Description:
Initializes the reference control block. Reference count is initialized to zero.
Arguments:
pRefCnt - pointer to uninitialized Reference Control Block InstanceHandle - handle to the managed instance. DeleteHandler - pointer to delete function, NULL is OK. TypeTag - Identifies initialization.
Return Value:
The function's value is VOID.
--*/
{ DEBUGMSG(DBG_REF, (TEXT("ReferenceInit(%#x, %#x, %#x, %c%c%c%c)\n"), pRefCnt, InstanceHandle, DeleteHandler, EXPAND_TAG(TypeTag)));
ASSERT(pRefCnt);
//
// Set the reference to 0 and save the instance
// handle and the delete handler.
//
pRefCnt->Count = 0; pRefCnt->Instance = InstanceHandle; pRefCnt->DeleteHandler = DeleteHandler;
pRefCnt->Sig = REF_SIG;
RtlZeroMemory(pRefCnt->Tags, sizeof(REF_TAG) * TAG_CNT);
pRefCnt->Tags[0].Tag = 'LTOT';
KeInitializeSpinLock(&pRefCnt->Lock);
pRefCnt->TypeTag = TypeTag;
return; }
VOID ReferenceAddDbg( PREF_CNT pRefCnt, ULONG Tag, int cLine ) { int i; int TotalPerArray = 0; KIRQL OldIrql;
ASSERT(pRefCnt->Sig == REF_SIG);
DEBUGMSG(DBG_REF && DBG_VERBOSE, (TEXT("REFADD %#x [%c%c%c%c:%c%c%c%c] %d [l:%d]\n"), pRefCnt, EXPAND_TAG(pRefCnt->TypeTag), EXPAND_TAG(Tag), pRefCnt->Count, cLine));
KeAcquireSpinLock(&pRefCnt->Lock, &OldIrql);
for (i = 1; i < TAG_CNT; i++) { if (pRefCnt->Tags[i].Tag == 0 || pRefCnt->Tags[i].Tag == Tag) { pRefCnt->Tags[i].Tag = Tag; InterlockedIncrement(&pRefCnt->Tags[i].Count); break; } }
ASSERT(i < TAG_CNT);
InterlockedIncrement(&pRefCnt->Tags[0].Count);
InterlockedIncrement(&pRefCnt->Count);
ASSERT(pRefCnt->Tags[0].Count == pRefCnt->Count);
#ifdef REFCNT_SANITY_CHECK
for (i = 1; i < TAG_CNT; i++) { if (pRefCnt->Tags[i].Tag != 0) { TotalPerArray += pRefCnt->Tags[i].Count; continue; } }
ASSERT(TotalPerArray == pRefCnt->Tags[0].Count); if (TotalPerArray != pRefCnt->Tags[0].Count) { DbgBreakPoint(); } #endif // REFCNT_SANITY_CHECK
KeReleaseSpinLock(&pRefCnt->Lock, OldIrql); }
VOID ReferenceRemoveDbg( PREF_CNT pRefCnt, ULONG Tag, int cLine) { int i; KIRQL OldIrql; int TotalPerArray = 0; BOOLEAN FoundIt = FALSE;
ASSERT(pRefCnt->Sig == REF_SIG);
KeAcquireSpinLock(&pRefCnt->Lock, &OldIrql);
DEBUGMSG(DBG_REF && DBG_VERBOSE, (TEXT("REFDEL %#x [%c%c%c%c:%c%c%c%c] %d [l:%d]\n"), pRefCnt, EXPAND_TAG(pRefCnt->TypeTag), EXPAND_TAG(Tag), pRefCnt->Count, cLine));
for (i = 1; i < TAG_CNT; i++) { if (pRefCnt->Tags[i].Tag == Tag) { FoundIt = TRUE;
ASSERT(pRefCnt->Tags[i].Count > 0);
InterlockedDecrement(&pRefCnt->Tags[i].Count); if (pRefCnt->Tags[i].Count == 0) { pRefCnt->Tags[i].Tag = Tag; } break; } }
ASSERT(FoundIt); ASSERT(pRefCnt->Tags[0].Count > 0); ASSERT(pRefCnt->Tags[0].Count == pRefCnt->Count);
InterlockedDecrement(&pRefCnt->Tags[0].Count);
//
// If the decremented count is non zero return the instance handle.
//
//
// If reference is zero and delete handler is available, then call
// handler.
//
if (InterlockedDecrement(&pRefCnt->Count) <= 0 && pRefCnt->DeleteHandler) { DEBUGMSG(DBG_REF,(TEXT("REFDEL %#x [%c%c%c%c:%c%c%c%c] calling delete handler [l:%d].\n"), pRefCnt, EXPAND_TAG(pRefCnt->TypeTag), EXPAND_TAG(Tag), cLine)); KeReleaseSpinLock(&pRefCnt->Lock, OldIrql);
(pRefCnt->DeleteHandler)(pRefCnt->Instance); } else { KeReleaseSpinLock(&pRefCnt->Lock, OldIrql); }
#ifdef REFCNT_SANITY_CHECK
for (i = 1; i < TAG_CNT; i++) { if (pRefCnt->Tags[i].Tag != 0) { TotalPerArray += pRefCnt->Tags[i].Count; continue; } } ASSERT(TotalPerArray == pRefCnt->Tags[0].Count); if (TotalPerArray != pRefCnt->Tags[0].Count) { DbgPrint(TEXT("Tag %X, RefCnt %X, perArray %d, total %d\n"), Tag, pRefCnt, TotalPerArray, pRefCnt->Tags[0].Count); DbgBreakPoint(); } #endif // REFCNT_SANITY_CHECK
} #endif // DBG
#endif // NDIS40
|