245 lines
5.4 KiB
C
245 lines
5.4 KiB
C
/*++
|
|
|
|
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
|