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.

244 lines
5.4 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. refcnt.c
  5. Abstract:
  6. This module contains checked reference counting support functions.
  7. The free versions are inline.
  8. Author:
  9. Scott Holden (sholden) 12/29/1998 Borrowed from IrDA.
  10. Revision History:
  11. --*/
  12. #ifdef NDIS40 // Only used for NDIS40 code now.
  13. #if DBG
  14. //
  15. // Include Files
  16. //
  17. #include "dlc.h"
  18. #include "llc.h"
  19. #include "dbgmsg.h"
  20. #define EXPAND_TAG(_Tag) ((CHAR *)(&_Tag))[0], \
  21. ((CHAR *)(&_Tag))[1], \
  22. ((CHAR *)(&_Tag))[2], \
  23. ((CHAR *)(&_Tag))[3]
  24. VOID
  25. ReferenceInitDbg(
  26. IN PREF_CNT pRefCnt,
  27. PVOID InstanceHandle,
  28. VOID (*DeleteHandler)(PVOID pvContext),
  29. ULONG TypeTag
  30. )
  31. /*++
  32. Routine Description:
  33. Initializes the reference control block. Reference count is initialized
  34. to zero.
  35. Arguments:
  36. pRefCnt - pointer to uninitialized Reference Control Block
  37. InstanceHandle - handle to the managed instance.
  38. DeleteHandler - pointer to delete function, NULL is OK.
  39. TypeTag - Identifies initialization.
  40. Return Value:
  41. The function's value is VOID.
  42. --*/
  43. {
  44. DEBUGMSG(DBG_REF, (TEXT("ReferenceInit(%#x, %#x, %#x, %c%c%c%c)\n"),
  45. pRefCnt, InstanceHandle, DeleteHandler, EXPAND_TAG(TypeTag)));
  46. ASSERT(pRefCnt);
  47. //
  48. // Set the reference to 0 and save the instance
  49. // handle and the delete handler.
  50. //
  51. pRefCnt->Count = 0;
  52. pRefCnt->Instance = InstanceHandle;
  53. pRefCnt->DeleteHandler = DeleteHandler;
  54. pRefCnt->Sig = REF_SIG;
  55. RtlZeroMemory(pRefCnt->Tags, sizeof(REF_TAG) * TAG_CNT);
  56. pRefCnt->Tags[0].Tag = 'LTOT';
  57. KeInitializeSpinLock(&pRefCnt->Lock);
  58. pRefCnt->TypeTag = TypeTag;
  59. return;
  60. }
  61. VOID
  62. ReferenceAddDbg(
  63. PREF_CNT pRefCnt,
  64. ULONG Tag,
  65. int cLine
  66. )
  67. {
  68. int i;
  69. int TotalPerArray = 0;
  70. KIRQL OldIrql;
  71. ASSERT(pRefCnt->Sig == REF_SIG);
  72. DEBUGMSG(DBG_REF && DBG_VERBOSE, (TEXT("REFADD %#x [%c%c%c%c:%c%c%c%c] %d [l:%d]\n"),
  73. pRefCnt, EXPAND_TAG(pRefCnt->TypeTag), EXPAND_TAG(Tag),
  74. pRefCnt->Count, cLine));
  75. KeAcquireSpinLock(&pRefCnt->Lock, &OldIrql);
  76. for (i = 1; i < TAG_CNT; i++)
  77. {
  78. if (pRefCnt->Tags[i].Tag == 0 || pRefCnt->Tags[i].Tag == Tag)
  79. {
  80. pRefCnt->Tags[i].Tag = Tag;
  81. InterlockedIncrement(&pRefCnt->Tags[i].Count);
  82. break;
  83. }
  84. }
  85. ASSERT(i < TAG_CNT);
  86. InterlockedIncrement(&pRefCnt->Tags[0].Count);
  87. InterlockedIncrement(&pRefCnt->Count);
  88. ASSERT(pRefCnt->Tags[0].Count == pRefCnt->Count);
  89. #ifdef REFCNT_SANITY_CHECK
  90. for (i = 1; i < TAG_CNT; i++)
  91. {
  92. if (pRefCnt->Tags[i].Tag != 0)
  93. {
  94. TotalPerArray += pRefCnt->Tags[i].Count;
  95. continue;
  96. }
  97. }
  98. ASSERT(TotalPerArray == pRefCnt->Tags[0].Count);
  99. if (TotalPerArray != pRefCnt->Tags[0].Count)
  100. {
  101. DbgBreakPoint();
  102. }
  103. #endif // REFCNT_SANITY_CHECK
  104. KeReleaseSpinLock(&pRefCnt->Lock, OldIrql);
  105. }
  106. VOID
  107. ReferenceRemoveDbg(
  108. PREF_CNT pRefCnt,
  109. ULONG Tag,
  110. int cLine)
  111. {
  112. int i;
  113. KIRQL OldIrql;
  114. int TotalPerArray = 0;
  115. BOOLEAN FoundIt = FALSE;
  116. ASSERT(pRefCnt->Sig == REF_SIG);
  117. KeAcquireSpinLock(&pRefCnt->Lock, &OldIrql);
  118. DEBUGMSG(DBG_REF && DBG_VERBOSE, (TEXT("REFDEL %#x [%c%c%c%c:%c%c%c%c] %d [l:%d]\n"),
  119. pRefCnt, EXPAND_TAG(pRefCnt->TypeTag), EXPAND_TAG(Tag),
  120. pRefCnt->Count, cLine));
  121. for (i = 1; i < TAG_CNT; i++)
  122. {
  123. if (pRefCnt->Tags[i].Tag == Tag)
  124. {
  125. FoundIt = TRUE;
  126. ASSERT(pRefCnt->Tags[i].Count > 0);
  127. InterlockedDecrement(&pRefCnt->Tags[i].Count);
  128. if (pRefCnt->Tags[i].Count == 0)
  129. {
  130. pRefCnt->Tags[i].Tag = Tag;
  131. }
  132. break;
  133. }
  134. }
  135. ASSERT(FoundIt);
  136. ASSERT(pRefCnt->Tags[0].Count > 0);
  137. ASSERT(pRefCnt->Tags[0].Count == pRefCnt->Count);
  138. InterlockedDecrement(&pRefCnt->Tags[0].Count);
  139. //
  140. // If the decremented count is non zero return the instance handle.
  141. //
  142. //
  143. // If reference is zero and delete handler is available, then call
  144. // handler.
  145. //
  146. if (InterlockedDecrement(&pRefCnt->Count) <= 0 &&
  147. pRefCnt->DeleteHandler)
  148. {
  149. DEBUGMSG(DBG_REF,(TEXT("REFDEL %#x [%c%c%c%c:%c%c%c%c] calling delete handler [l:%d].\n"),
  150. pRefCnt, EXPAND_TAG(pRefCnt->TypeTag), EXPAND_TAG(Tag), cLine));
  151. KeReleaseSpinLock(&pRefCnt->Lock, OldIrql);
  152. (pRefCnt->DeleteHandler)(pRefCnt->Instance);
  153. }
  154. else
  155. {
  156. KeReleaseSpinLock(&pRefCnt->Lock, OldIrql);
  157. }
  158. #ifdef REFCNT_SANITY_CHECK
  159. for (i = 1; i < TAG_CNT; i++)
  160. {
  161. if (pRefCnt->Tags[i].Tag != 0)
  162. {
  163. TotalPerArray += pRefCnt->Tags[i].Count;
  164. continue;
  165. }
  166. }
  167. ASSERT(TotalPerArray == pRefCnt->Tags[0].Count);
  168. if (TotalPerArray != pRefCnt->Tags[0].Count)
  169. {
  170. DbgPrint(TEXT("Tag %X, RefCnt %X, perArray %d, total %d\n"), Tag, pRefCnt,
  171. TotalPerArray, pRefCnt->Tags[0].Count);
  172. DbgBreakPoint();
  173. }
  174. #endif // REFCNT_SANITY_CHECK
  175. }
  176. #endif // DBG
  177. #endif // NDIS40