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.

321 lines
8.4 KiB

  1. /****************************************************************************/
  2. // misc.c
  3. //
  4. // Miscellaneous TermDD routines.
  5. //
  6. // Copyright (C) 1998-2000 Microsoft Corporation
  7. /****************************************************************************/
  8. #include <precomp.h>
  9. #pragma hdrstop
  10. #if DBG
  11. LIST_ENTRY IcaGlobalPoolListHead;
  12. ULONG IcaTotalAllocations = 0;
  13. ULONG IcaTotalFrees = 0;
  14. ULONG IcaTotalBytesAllocated = 0;
  15. KSPIN_LOCK IcaDebugSpinLock;
  16. typedef struct _ICA_POOL_HEADER {
  17. LIST_ENTRY GlobalPoolListEntry;
  18. PCHAR FileName;
  19. ULONG LineNumber;
  20. ULONG Size;
  21. ULONG InUse;
  22. } ICA_POOL_HEADER, *PICA_POOL_HEADER;
  23. typedef struct _ICA_POOL_TRAILER {
  24. ULONG Size;
  25. ULONG_PTR CheckSum;
  26. } ICA_POOL_TRAILER, *PICA_POOL_TRAILER;
  27. void IcaInitializeDebugData(void)
  28. {
  29. KeInitializeSpinLock(&IcaDebugSpinLock);
  30. InitializeListHead(&IcaGlobalPoolListHead);
  31. }
  32. BOOLEAN IcaLockConnection(PICA_CONNECTION pConnect)
  33. {
  34. PERESOURCE pResource = &pConnect->Resource;
  35. PLIST_ENTRY Head, Next;
  36. PICA_STACK pStack;
  37. KIRQL oldIrql;
  38. ULONG i;
  39. BOOLEAN Result;
  40. TRACE((pConnect, TC_ICADD, TT_SEM,
  41. "TermDD: IcaLockConnection: 0x%x\n", pResource));
  42. /*
  43. * Ensure we don't already have the connection locked
  44. */
  45. ASSERT( !ExIsResourceAcquiredExclusiveLite( pResource ) );
  46. /*
  47. * Reference and lock the connection object
  48. */
  49. IcaReferenceConnection( pConnect );
  50. KeEnterCriticalRegion(); // Disable APC calls when holding a resource.
  51. Result = ExAcquireResourceExclusive( pResource, TRUE );
  52. /*
  53. * Ensure we don't own any stack locks
  54. */
  55. Head = &pConnect->StackHead;
  56. for ( Next = Head->Flink; Next != Head; Next = Next->Flink ) {
  57. pStack = CONTAINING_RECORD( Next, ICA_STACK, StackEntry );
  58. ASSERT( !ExIsResourceAcquiredExclusiveLite( &pStack->Resource ) );
  59. }
  60. /*
  61. * Ensure we don't own any channel locks
  62. */
  63. IcaLockChannelTable(&pConnect->ChannelTableLock);
  64. for ( i = 0; i < sizeof(pConnect->pChannel) / sizeof(*pConnect->pChannel); i++ ) {
  65. if (pConnect->pChannel[i]) {
  66. ASSERT(!ExIsResourceAcquiredExclusiveLite(&pConnect->pChannel[i]->Resource));
  67. }
  68. }
  69. IcaUnlockChannelTable(&pConnect->ChannelTableLock);
  70. return Result;
  71. }
  72. void IcaUnlockConnection(PICA_CONNECTION pConnect)
  73. {
  74. PERESOURCE pResource = &pConnect->Resource;
  75. TRACE((pConnect, TC_ICADD, TT_SEM,
  76. "TermDD: IcaUnlockConnection: 0x%x\n", pResource));
  77. /*
  78. * Ensure we already have the connection locked
  79. */
  80. ASSERT(ExIsResourceAcquiredExclusiveLite(pResource));
  81. ExReleaseResource(pResource);
  82. KeLeaveCriticalRegion(); // Resume APC calls after releasing resource.
  83. IcaDereferenceConnection(pConnect);
  84. }
  85. BOOLEAN IcaLockStack(PICA_STACK pStack)
  86. {
  87. PERESOURCE pResource = &pStack->Resource;
  88. PICA_CONNECTION pConnect;
  89. PLIST_ENTRY Head, Next;
  90. PICA_STACK pNextStack;
  91. KIRQL oldIrql;
  92. ULONG i;
  93. BOOLEAN Result;
  94. /*
  95. * Ensure we don't already have the stack locked
  96. */
  97. ASSERT( !ExIsResourceAcquiredExclusiveLite( pResource ) );
  98. /*
  99. * Reference and lock the stack object
  100. */
  101. IcaReferenceStack( pStack );
  102. KeEnterCriticalRegion(); // Disable APC calls when holding a resource.
  103. Result = ExAcquireResourceExclusive( pResource, TRUE );
  104. TRACESTACK((pStack, TC_ICADD, TT_SEM,
  105. "TermDD: IcaLockStack: 0x%x\n", pStack));
  106. /*
  107. * Ensure we don't own any other stack locks
  108. */
  109. pConnect = IcaGetConnectionForStack( pStack );
  110. Head = &pConnect->StackHead;
  111. for ( Next = Head->Flink; Next != Head; Next = Next->Flink ) {
  112. pNextStack = CONTAINING_RECORD( Next, ICA_STACK, StackEntry );
  113. if ( pNextStack != pStack ) {
  114. ASSERT( !ExIsResourceAcquiredExclusiveLite( &pNextStack->Resource ) );
  115. }
  116. }
  117. /*
  118. * Ensure we don't own any channel locks
  119. */
  120. IcaLockChannelTable(&pConnect->ChannelTableLock);
  121. for ( i = 0; i < sizeof(pConnect->pChannel) / sizeof(*pConnect->pChannel); i++ ) {
  122. if ( pConnect->pChannel[i] ) {
  123. ASSERT( !ExIsResourceAcquiredExclusiveLite( &pConnect->pChannel[i]->Resource ) );
  124. }
  125. }
  126. IcaUnlockChannelTable(&pConnect->ChannelTableLock);
  127. return Result;
  128. }
  129. void IcaUnlockStack(PICA_STACK pStack)
  130. {
  131. PERESOURCE pResource = &pStack->Resource;
  132. TRACESTACK((pStack, TC_ICADD, TT_SEM,
  133. "TermDD: IcaUnlockStack: 0x%x\n", pStack));
  134. /*
  135. * Ensure we already have the stack locked
  136. */
  137. ASSERT(ExIsResourceAcquiredExclusiveLite(pResource));
  138. ExReleaseResource(pResource);
  139. KeLeaveCriticalRegion(); // Resume APC calls after releasing resource.
  140. IcaDereferenceStack(pStack);
  141. }
  142. BOOLEAN IcaLockChannel(PICA_CHANNEL pChannel)
  143. {
  144. PERESOURCE pResource = &pChannel->Resource;
  145. TRACECHANNEL((pChannel, TC_ICADD, TT_SEM,
  146. "TermDD: IcaLockChannel: cc %u, vc %d\n",
  147. pChannel->ChannelClass, pChannel->VirtualClass));
  148. IcaReferenceChannel(pChannel);
  149. // Need to disable APC calls when holding a resource.
  150. KeEnterCriticalRegion();
  151. return ExAcquireResourceExclusive(pResource, TRUE);
  152. }
  153. void IcaUnlockChannel(IN PICA_CHANNEL pChannel)
  154. {
  155. PERESOURCE pResource = &pChannel->Resource;
  156. TRACECHANNEL((pChannel, TC_ICADD, TT_SEM,
  157. "TermDD: IcaUnlockChannel: cc %u, vc %d\n",
  158. pChannel->ChannelClass, pChannel->VirtualClass));
  159. /*
  160. * Ensure we already have the channel locked
  161. */
  162. ASSERT(ExIsResourceAcquiredExclusiveLite(pResource));
  163. ExReleaseResource(pResource);
  164. KeLeaveCriticalRegion(); // Resume APC calls after releasing resource.
  165. IcaDereferenceChannel(pChannel);
  166. }
  167. PVOID IcaAllocatePool(
  168. IN POOL_TYPE PoolType,
  169. IN ULONG NumberOfBytes,
  170. IN PCHAR FileName,
  171. IN ULONG LineNumber,
  172. IN BOOLEAN WithQuota)
  173. {
  174. PICA_POOL_HEADER header;
  175. PICA_POOL_TRAILER trailer;
  176. KIRQL oldIrql;
  177. ASSERT( PoolType == NonPagedPool || PoolType == NonPagedPoolMustSucceed );
  178. // make sure number of bytes are 64bit aligned
  179. NumberOfBytes = (NumberOfBytes + 7) & ~7;
  180. if (WithQuota) {
  181. try {
  182. header = ExAllocatePoolWithQuotaTag(
  183. PoolType,
  184. NumberOfBytes + sizeof(*header) + sizeof(*trailer),
  185. ICA_POOL_TAG
  186. );
  187. } except( EXCEPTION_EXECUTE_HANDLER ) {
  188. return NULL;
  189. }
  190. } else {
  191. header = ExAllocatePoolWithTag(
  192. PoolType,
  193. NumberOfBytes + sizeof(*header) + sizeof(*trailer),
  194. ICA_POOL_TAG
  195. );
  196. }
  197. if (header == NULL) {
  198. return NULL;
  199. }
  200. header->FileName = FileName;
  201. header->LineNumber = LineNumber;
  202. header->Size = NumberOfBytes;
  203. header->InUse = 1;
  204. trailer = (PICA_POOL_TRAILER)((PCHAR)(header + 1) + NumberOfBytes);
  205. trailer->Size = NumberOfBytes;
  206. trailer->CheckSum = (ULONG_PTR)header + (ULONG_PTR)FileName + LineNumber +
  207. NumberOfBytes;
  208. InterlockedIncrement(
  209. &IcaTotalAllocations
  210. );
  211. ExInterlockedAddUlong(
  212. &IcaTotalBytesAllocated,
  213. header->Size,
  214. &IcaDebugSpinLock
  215. );
  216. ExInterlockedInsertTailList( &IcaGlobalPoolListHead,
  217. &header->GlobalPoolListEntry,
  218. &IcaDebugSpinLock );
  219. return (PVOID)(header + 1);
  220. }
  221. void IcaFreePool(IN PVOID Pointer)
  222. {
  223. KIRQL oldIrql;
  224. PICA_POOL_HEADER header = (PICA_POOL_HEADER)Pointer - 1;
  225. PICA_POOL_TRAILER trailer;
  226. trailer = (PICA_POOL_TRAILER)((PCHAR)(header + 1) + header->Size);
  227. ASSERT( header->Size == trailer->Size );
  228. ASSERT( trailer->CheckSum = (ULONG_PTR)header + (ULONG_PTR)header->FileName +
  229. header->LineNumber + header->Size );
  230. InterlockedIncrement(
  231. &IcaTotalFrees
  232. );
  233. ExInterlockedAddUlong(
  234. &IcaTotalBytesAllocated,
  235. -1*header->Size,
  236. &IcaDebugSpinLock
  237. );
  238. KeAcquireSpinLock( &IcaDebugSpinLock, &oldIrql );
  239. RemoveEntryList( &header->GlobalPoolListEntry );
  240. KeReleaseSpinLock( &IcaDebugSpinLock, oldIrql );
  241. header->GlobalPoolListEntry.Flink = (PLIST_ENTRY)(-1);
  242. header->GlobalPoolListEntry.Blink = (PLIST_ENTRY)(-1);
  243. header->InUse = 0;
  244. if (header->Size == trailer->Size)
  245. RtlFillMemory(Pointer, header->Size, 0xff);
  246. ExFreePool((PVOID)header);
  247. }
  248. #endif