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.

294 lines
5.0 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. PSLIST_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. PSLIST_ENTRY ListEntry;
  144. //
  145. // Allocating the BUFFER_POOL_HANDLE ( via a call to CreateBufferPool ) may have
  146. // failed, so handle this case
  147. //
  148. if ( Handle == NULL )
  149. {
  150. return NULL;
  151. }
  152. InterlockedIncrement(&BufferPool->ReferenceCount);
  153. ListEntry=ExInterlockedPopEntrySList(
  154. &BufferPool->ListHead,
  155. &BufferPool->SpinLock
  156. );
  157. if (ListEntry != NULL) {
  158. PIRCOMM_BUFFER Buffer=CONTAINING_RECORD(ListEntry,IRCOMM_BUFFER,ListEntry);
  159. #if DBG
  160. InterlockedIncrement(&BufferPool->BufferInUse);
  161. Buffer->FreeBuffer=FreeBuffer;
  162. #endif
  163. return Buffer;
  164. }
  165. RemoveReferenceOnBufferPool(BufferPool);
  166. return NULL;
  167. }
  168. VOID
  169. FreeBuffer(
  170. PIRCOMM_BUFFER Buffer
  171. )
  172. {
  173. PBUFFER_POOL BufferPool=Buffer->BufferPool;
  174. #if DBG
  175. Buffer->FreeBuffer=NULL;
  176. Buffer->Context=NULL;
  177. IoReuseIrp(Buffer->Irp,STATUS_CANCELLED);
  178. InterlockedDecrement(&BufferPool->BufferInUse);
  179. #endif
  180. ExInterlockedPushEntrySList(
  181. &BufferPool->ListHead,
  182. &Buffer->ListEntry,
  183. &BufferPool->SpinLock
  184. );
  185. RemoveReferenceOnBufferPool(BufferPool);
  186. return;
  187. }