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.

285 lines
4.6 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. buffer.c
  5. Abstract:
  6. This module contains the code that is very specific to initialization
  7. and unload operations in the irenum driver
  8. Author:
  9. Brian Lieuallen, 7-13-2000
  10. Environment:
  11. Kernel mode
  12. Revision History :
  13. --*/
  14. #include <ntddk.h>
  15. #include <buffer.h>
  16. #include <ircommdbg.h>
  17. typedef struct _BUFFER_POOL {
  18. KSPIN_LOCK SpinLock;
  19. SLIST_HEADER ListHead;
  20. LONG ReferenceCount;
  21. #if DBG
  22. LONG TotalBuffers;
  23. LONG BufferInUse;
  24. BOOLEAN Freed;
  25. #endif
  26. } BUFFER_POOL, *PBUFFER_POOL;
  27. VOID
  28. FreeBuffer(
  29. PIRCOMM_BUFFER Buffer
  30. );
  31. VOID
  32. RemoveReferenceOnBufferPool(
  33. PBUFFER_POOL BufferPool
  34. )
  35. {
  36. LONG Count=InterlockedDecrement(&BufferPool->ReferenceCount);
  37. if (Count == 0) {
  38. PSINGLE_LIST_ENTRY ListEntry;
  39. ASSERT(BufferPool->Freed);
  40. ListEntry=ExInterlockedPopEntrySList(
  41. &BufferPool->ListHead,
  42. &BufferPool->SpinLock
  43. );
  44. while (ListEntry != NULL) {
  45. PIRCOMM_BUFFER Buffer=CONTAINING_RECORD(ListEntry,IRCOMM_BUFFER,ListEntry);
  46. IoFreeIrp(Buffer->Irp);
  47. IoFreeMdl(Buffer->Mdl);
  48. FREE_POOL(Buffer);
  49. ListEntry=ExInterlockedPopEntrySList(
  50. &BufferPool->ListHead,
  51. &BufferPool->SpinLock
  52. );
  53. }
  54. FREE_POOL(BufferPool);
  55. }
  56. return;
  57. }
  58. BUFFER_POOL_HANDLE
  59. CreateBufferPool(
  60. ULONG StackDepth,
  61. ULONG BufferSize,
  62. ULONG BufferCount
  63. )
  64. {
  65. PBUFFER_POOL BufferPool;
  66. ULONG i;
  67. BufferPool=ALLOCATE_NONPAGED_POOL(sizeof(*BufferPool));
  68. if (BufferPool == NULL) {
  69. return NULL;
  70. }
  71. BufferPool->ReferenceCount=1;
  72. #if DBG
  73. BufferPool->BufferInUse=0;
  74. BufferPool->TotalBuffers=BufferCount;
  75. BufferPool->Freed=FALSE;
  76. #endif
  77. KeInitializeSpinLock(
  78. &BufferPool->SpinLock
  79. );
  80. ExInitializeSListHead(
  81. &BufferPool->ListHead
  82. );
  83. for (i=0; i<BufferCount; i++) {
  84. PIRCOMM_BUFFER Buffer;
  85. Buffer=ALLOCATE_NONPAGED_POOL(FIELD_OFFSET(IRCOMM_BUFFER,Data[0])+BufferSize);
  86. if (Buffer == NULL) {
  87. goto CleanUp;
  88. }
  89. Buffer->BufferLength=BufferSize;
  90. #if !DBG
  91. Buffer->FreeBuffer=FreeBuffer;
  92. #endif
  93. Buffer->BufferPool=BufferPool;
  94. Buffer->Irp=IoAllocateIrp((CCHAR)StackDepth,FALSE);
  95. if (Buffer->Irp == NULL) {
  96. FREE_POOL(Buffer);
  97. goto CleanUp;
  98. }
  99. Buffer->Mdl=IoAllocateMdl(
  100. &Buffer->Data[0],
  101. BufferSize,
  102. FALSE, // primary
  103. FALSE, // chage quota
  104. NULL
  105. );
  106. if (Buffer->Mdl == NULL) {
  107. IoFreeIrp(Buffer->Irp);
  108. FREE_POOL(Buffer);
  109. goto CleanUp;
  110. }
  111. MmBuildMdlForNonPagedPool(
  112. Buffer->Mdl
  113. );
  114. ExInterlockedPushEntrySList(
  115. &BufferPool->ListHead,
  116. &Buffer->ListEntry,
  117. &BufferPool->SpinLock
  118. );
  119. }
  120. return BufferPool;
  121. CleanUp:
  122. FreeBufferPool(BufferPool);
  123. return NULL;
  124. }
  125. VOID
  126. FreeBufferPool(
  127. BUFFER_POOL_HANDLE Handle
  128. )
  129. {
  130. PBUFFER_POOL BufferPool=Handle;
  131. #if DBG
  132. BufferPool->Freed=TRUE;
  133. #endif
  134. RemoveReferenceOnBufferPool(BufferPool);
  135. return;
  136. }
  137. PIRCOMM_BUFFER
  138. GetBuffer(
  139. BUFFER_POOL_HANDLE Handle
  140. )
  141. {
  142. PBUFFER_POOL BufferPool=Handle;
  143. PSINGLE_LIST_ENTRY ListEntry;
  144. InterlockedIncrement(&BufferPool->ReferenceCount);
  145. ListEntry=ExInterlockedPopEntrySList(
  146. &BufferPool->ListHead,
  147. &BufferPool->SpinLock
  148. );
  149. if (ListEntry != NULL) {
  150. PIRCOMM_BUFFER Buffer=CONTAINING_RECORD(ListEntry,IRCOMM_BUFFER,ListEntry);
  151. #if DBG
  152. InterlockedIncrement(&BufferPool->BufferInUse);
  153. Buffer->FreeBuffer=FreeBuffer;
  154. #endif
  155. return Buffer;
  156. }
  157. RemoveReferenceOnBufferPool(BufferPool);
  158. return NULL;
  159. }
  160. VOID
  161. FreeBuffer(
  162. PIRCOMM_BUFFER Buffer
  163. )
  164. {
  165. PBUFFER_POOL BufferPool=Buffer->BufferPool;
  166. #if DBG
  167. Buffer->FreeBuffer=NULL;
  168. Buffer->Context=NULL;
  169. IoReuseIrp(Buffer->Irp,STATUS_CANCELLED);
  170. InterlockedDecrement(&BufferPool->BufferInUse);
  171. #endif
  172. ExInterlockedPushEntrySList(
  173. &BufferPool->ListHead,
  174. &Buffer->ListEntry,
  175. &BufferPool->SpinLock
  176. );
  177. RemoveReferenceOnBufferPool(BufferPool);
  178. return;
  179. }