Leaked source code of windows server 2003
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.

353 lines
7.0 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. refcnt.c
  5. Abstract:
  6. This module exports Reference Counting support functions. By
  7. including a Reference Count Control Block (REF_CNT) in a
  8. dynamic type, and using this API, a Reference scheme can be
  9. implemented for that type.
  10. Author:
  11. Edward Buchwalter (v-edbuc) 14-Aug-1996
  12. Revision History:
  13. --*/
  14. //
  15. // Include Files
  16. //
  17. #include "irda.h"
  18. #undef offsetof
  19. #include "refcnt.tmh"
  20. #define EXPAND_TAG(t) ((CHAR *)(&Tag))[0],((CHAR *)(&Tag))[1],((CHAR *)(&Tag))[2],((CHAR *)(&Tag))[3]
  21. VOID
  22. ReferenceInit
  23. (
  24. IN PREF_CNT pRefCnt,
  25. PVOID InstanceHandle,
  26. VOID (*DeleteHandler)( PVOID )
  27. )
  28. /*++
  29. Routine Description:
  30. ReferenceInit initializes and adds one reference to the
  31. supplied Reference Control Block. If provided, an instance
  32. handle and delete handler are saved for use by the ReferenceRemove
  33. function when all references to the instance are removed.
  34. Arguments:
  35. pRefCnt - pointer to uninitialized Reference Control Block
  36. InstanceHandle - handle to the managed instance.
  37. DeleteHandler - pointer to delete function, NULL is OK.
  38. Return Value:
  39. The function's value is VOID.
  40. --*/
  41. {
  42. DEBUGMSG( DBG_REF,( TEXT("ReferenceInit( 0x%p, 0x%p, 0x%p )\n"),
  43. pRefCnt, InstanceHandle, DeleteHandler ));
  44. ASSERT( pRefCnt );
  45. // Set the reference to 1 and save the instance
  46. // handle and the delete handler.
  47. pRefCnt->Count = 0;
  48. pRefCnt->Instance = InstanceHandle;
  49. pRefCnt->DeleteHandler = DeleteHandler;
  50. #if DBG
  51. pRefCnt->Sig = REF_SIG;
  52. RtlZeroMemory(pRefCnt->Tags, sizeof(REF_TAG) * TAG_CNT);
  53. pRefCnt->Tags[0].Tag = 'LTOT';
  54. CTEInitLock(&pRefCnt->Lock);
  55. #endif
  56. }
  57. VOID
  58. ReferenceAdd
  59. (
  60. IN PREF_CNT pRefCnt
  61. )
  62. /*++
  63. Routine Description:
  64. Arguments:
  65. Return Value:
  66. --*/
  67. {
  68. ASSERT( pRefCnt );
  69. InterlockedIncrement(&pRefCnt->Count);
  70. // DEBUGMSG( DBG_REF,( TEXT("R+%d\n"), pRefCnt->Count ));
  71. }
  72. VOID
  73. ReferenceAddCount
  74. (
  75. IN PREF_CNT pRefCnt,
  76. IN UINT Count
  77. )
  78. /*++
  79. Routine Description:
  80. Arguments:
  81. Return Value:
  82. --*/
  83. {
  84. ASSERT( pRefCnt->Count > 0 );
  85. CTEInterlockedExchangeAdd(&pRefCnt->Count, Count);
  86. }
  87. VOID
  88. ReferenceRemove
  89. (
  90. IN PREF_CNT pRefCnt
  91. )
  92. /*++
  93. Routine Description:
  94. Arguments:
  95. Return Value:
  96. --*/
  97. {
  98. ASSERT( pRefCnt );
  99. // Trap remove reference on a zero count
  100. ASSERT( pRefCnt->Count > 0 );
  101. // If the decremented count is non zero return the instance handle
  102. if (InterlockedDecrement(&pRefCnt->Count) > 0 )
  103. {
  104. // DEBUGMSG( DBG_REF,( TEXT("R-%d\n"), pRefCnt->Count ));
  105. // DEBUGMSG( DBG_REF,( TEXT("ReferenceRemove:remaining: %d\n"), pRefCnt->Count ));
  106. return;
  107. }
  108. // Delete this instance if a delete handler is available
  109. if( pRefCnt->DeleteHandler )
  110. {
  111. DEBUGMSG( DBG_REF,( TEXT("Executing DeleteHandler\n") ));
  112. (pRefCnt->DeleteHandler)( pRefCnt->Instance );
  113. }
  114. // Indicate no active references to this instance
  115. return;
  116. }
  117. //
  118. // API Test Support
  119. //
  120. #if DBG
  121. #if 0
  122. VOID
  123. ReferenceApiTest( VOID )
  124. {
  125. REF_CNT RefCnt;
  126. DEBUGMSG( DBG_REF,( TEXT("\nReferenceApiTest\n") ));
  127. DEBUGMSG( DBG_REF,( TEXT("\nTest #1: NULL delete handler\n") ));
  128. ReferenceInit( &RefCnt, &RefCnt, NULL );
  129. ReferenceAdd( &RefCnt );
  130. ReferenceAdd( &RefCnt );
  131. ReferenceAdd( &RefCnt );
  132. while( ReferenceRemove( &RefCnt ) )
  133. {
  134. ;
  135. }
  136. DEBUGMSG( DBG_REF,( TEXT("\nTest #2: Delete Handler - TBD\n") ));
  137. }
  138. #endif
  139. VOID
  140. ReferenceAddDbg(PREF_CNT pRefCnt, ULONG Tag)
  141. {
  142. int i;
  143. CTELockHandle hLock;
  144. int TotalPerArray = 0;
  145. ASSERT(pRefCnt->Sig == REF_SIG);
  146. DEBUGMSG(DBG_REF, (TEXT("IRREF: add %p (%c%c%c%c) %d\n"),
  147. pRefCnt, (char)Tag,(char)(Tag>>8),(char)(Tag>>16),(char)(Tag>>24), pRefCnt->Count));
  148. CTEGetLock(&pRefCnt->Lock, &hLock);
  149. for (i = 1; i < TAG_CNT; i++)
  150. {
  151. if (pRefCnt->Tags[i].Tag == 0 || pRefCnt->Tags[i].Tag == Tag)
  152. {
  153. pRefCnt->Tags[i].Tag = Tag;
  154. InterlockedIncrement(&pRefCnt->Tags[i].Count);
  155. break;
  156. }
  157. }
  158. ASSERT(i < TAG_CNT);
  159. InterlockedIncrement(&pRefCnt->Tags[0].Count);
  160. InterlockedIncrement(&pRefCnt->Count);
  161. ASSERT(pRefCnt->Tags[0].Count == pRefCnt->Count);
  162. // sanity check
  163. /*
  164. for (i = 1; i < TAG_CNT; i++)
  165. {
  166. if (pRefCnt->Tags[i].Tag != 0)
  167. {
  168. TotalPerArray += pRefCnt->Tags[i].Count;
  169. continue;
  170. }
  171. }
  172. ASSERT(TotalPerArray == pRefCnt->Tags[0].Count);
  173. if (TotalPerArray != pRefCnt->Tags[0].Count)
  174. {
  175. DbgBreakPoint();
  176. }
  177. */
  178. CTEFreeLock(&pRefCnt->Lock, hLock);
  179. }
  180. VOID
  181. ReferenceRemoveDbg(PREF_CNT pRefCnt, ULONG Tag)
  182. {
  183. int i;
  184. CTELockHandle hLock;
  185. int TotalPerArray = 0;
  186. BOOLEAN FoundIt = FALSE;
  187. ASSERT(pRefCnt->Sig == REF_SIG);
  188. DEBUGMSG(DBG_REF, (TEXT("IRREF: remove %p (%c%c%c%c) %d\n"),
  189. pRefCnt, (char)Tag, (char)(Tag>>8), (char)(Tag>>16), (char)(Tag>>24), pRefCnt->Count));
  190. CTEGetLock(&pRefCnt->Lock, &hLock);
  191. for (i = 1; i < TAG_CNT; i++)
  192. {
  193. if (pRefCnt->Tags[i].Tag == Tag)
  194. {
  195. FoundIt = TRUE;
  196. ASSERT(pRefCnt->Tags[i].Count > 0);
  197. InterlockedDecrement(&pRefCnt->Tags[i].Count);
  198. if (pRefCnt->Tags[i].Count == 0)
  199. pRefCnt->Tags[i].Tag = Tag;
  200. break;
  201. }
  202. }
  203. ASSERT(FoundIt);
  204. ASSERT(pRefCnt->Tags[0].Count > 0);
  205. ASSERT(pRefCnt->Tags[0].Count == pRefCnt->Count);
  206. InterlockedDecrement(&pRefCnt->Tags[0].Count);
  207. if (InterlockedDecrement(&pRefCnt->Count) > 0 )
  208. {
  209. CTEFreeLock(&pRefCnt->Lock, hLock);
  210. }
  211. else if (pRefCnt->DeleteHandler)
  212. {
  213. DEBUGMSG( DBG_REF,( TEXT("Executing DeleteHandler\n") ));
  214. CTEFreeLock(&pRefCnt->Lock, hLock);
  215. (pRefCnt->DeleteHandler)( pRefCnt->Instance );
  216. }
  217. else
  218. {
  219. CTEFreeLock(&pRefCnt->Lock, hLock);
  220. }
  221. /*
  222. // sanity check
  223. for (i = 1; i < TAG_CNT; i++)
  224. {
  225. if (pRefCnt->Tags[i].Tag != 0)
  226. {
  227. TotalPerArray += pRefCnt->Tags[i].Count;
  228. continue;
  229. }
  230. }
  231. ASSERT(TotalPerArray == pRefCnt->Tags[0].Count);
  232. if (TotalPerArray != pRefCnt->Tags[0].Count)
  233. {
  234. DbgPrint(TEXT("Tag %X, RefCnt %p, perArray %d, total %d\n"), Tag, pRefCnt,
  235. TotalPerArray, pRefCnt->Tags[0].Count);
  236. DbgBreakPoint();
  237. }
  238. */
  239. }
  240. #endif