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.

377 lines
9.8 KiB

  1. /*++
  2. Copyright (c) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. buf.c
  5. Abstract:
  6. Buffer management utilities
  7. Revision History:
  8. Who When What
  9. -------- -------- ----------------------------------------------
  10. josephj 03-10-99 Created
  11. Notes:
  12. --*/
  13. #include <precomp.h>
  14. //
  15. // File-specific debugging defaults.
  16. //
  17. #define TM_CURRENT TM_BUF
  18. NDIS_STATUS
  19. arpInitializeConstBufferPool(
  20. IN UINT NumBuffersToCache,
  21. IN UINT MaxBuffers,
  22. IN const PVOID pvMem,
  23. IN UINT cbMem,
  24. IN PRM_OBJECT_HEADER pOwningObject,
  25. IN OUT ARP_CONST_BUFFER_POOL * pHdrPool,
  26. IN PRM_STACK_RECORD pSR
  27. )
  28. /*++
  29. Routine Description:
  30. Initialize a pool of pre-initialized buffers (of type NDIS_BUFFER). Each buffer
  31. points to the same, CONSTANT piece of virtual memory, that is supplied by
  32. the caller (pvMem, of size cbMem).
  33. Arguments:
  34. NumBuffersToCache - Max number of pre-initialized buffers to keep in the
  35. internal cache.
  36. MaxBuffers - Max number of buffers allowed to be allocated at any one
  37. time.
  38. pvMem - The constant piece of memory that all the buffers point
  39. to.
  40. cbMem - The size (in bytes) of the above piece of memory.
  41. pOwningObject - The object that owns the const buffer pool.
  42. pHdrPool - Unitialized memory to hold the const buffer pool.
  43. Return Value:
  44. NDIS_STATUS_SUCCESS on successfill initialization of the const buffer pool.
  45. NDIS failure code on failure.
  46. --*/
  47. {
  48. ENTER("arpInitializeConstBufferPool", 0x943463d4)
  49. NDIS_STATUS Status;
  50. ARP_ZEROSTRUCT(pHdrPool);
  51. do
  52. {
  53. // Allocate the buffer pool
  54. //
  55. NdisAllocateBufferPool(
  56. &Status,
  57. &pHdrPool->NdisHandle,
  58. MaxBuffers
  59. );
  60. if (FAIL(Status))
  61. {
  62. TR_WARN((
  63. "pOwningObj 0x%p, NdisAllocateBufferPool err status 0x%x\n",
  64. pOwningObject, Status));
  65. break;
  66. }
  67. pHdrPool->NumBuffersToCache = NumBuffersToCache;
  68. pHdrPool->MaxBuffers = MaxBuffers;
  69. pHdrPool->pvMem = pvMem;
  70. pHdrPool->cbMem = cbMem;
  71. pHdrPool->pOwningObject = pOwningObject;
  72. // Initialize Slist to contain initialized and available buffers.
  73. //
  74. ExInitializeSListHead(&pHdrPool->BufferList);
  75. // Initialize spin lock that serializes accesses to the above list.
  76. //
  77. NdisAllocateSpinLock(&pHdrPool->NdisLock);
  78. // (DBG) Add an association to the owning object, to make sure that it
  79. // deallocates us eventually!
  80. //
  81. DBG_ADDASSOC(
  82. pOwningObject,
  83. pHdrPool, // Entity1
  84. NULL, // Entity2 (unused)
  85. ARPASSOC_CBUFPOOL_ALLOC, // AssocID
  86. " Buffer pool 0x%p\n", // Format string
  87. pSR
  88. );
  89. //
  90. // Note: we don't populate the list at this stage -- instead we add items on
  91. // demand.
  92. //
  93. Status = NDIS_STATUS_SUCCESS;
  94. } while (FALSE);
  95. EXIT()
  96. return Status;
  97. }
  98. VOID
  99. arpDeinitializeConstBufferPool(
  100. IN ARP_CONST_BUFFER_POOL *pHdrPool,
  101. IN PRM_STACK_RECORD pSR
  102. )
  103. /*++
  104. Routine Description:
  105. Deinitialize a previously-initialized const buffer pool. Free all buffers.
  106. buffers. This function must ONLY be called when there are no outstanding
  107. allocated buffers.
  108. Arguments:
  109. pHdrPool - const buffer pool to deinitialize
  110. --*/
  111. {
  112. SLIST_ENTRY * pListEntry;
  113. ENTER("arpDeinitializeConstBufferPool", 0x0db6f5b2)
  114. // There should be no outstanding buffers...
  115. //
  116. ASSERTEX(pHdrPool->NumAllocd == pHdrPool->NumInCache, pHdrPool);
  117. // (DBG) Delete the association we assume was previously added when pHdrPool
  118. // was initialized.
  119. //
  120. DBG_DELASSOC(
  121. pHdrPool->pOwningObject,
  122. pHdrPool, // Entity1
  123. NULL, // Entity2 (unused)
  124. ARPASSOC_CBUFPOOL_ALLOC, // AssocID
  125. pSR
  126. );
  127. // Free any buffers in the cache...
  128. //
  129. while(1) {
  130. pListEntry = ExInterlockedPopEntrySList(
  131. &pHdrPool->BufferList,
  132. &pHdrPool->NdisLock.SpinLock
  133. );
  134. if (pListEntry!=NULL)
  135. {
  136. PNDIS_BUFFER pNdisBuffer = STRUCT_OF(NDIS_BUFFER, pListEntry, Next);
  137. InterlockedDecrement(&pHdrPool->NumInCache);
  138. NDIS_BUFFER_LINKAGE(pNdisBuffer) = NULL;
  139. NdisFreeBuffer(pNdisBuffer);
  140. }
  141. else
  142. {
  143. break;
  144. }
  145. }
  146. ASSERTEX(pHdrPool->NumInCache==0, pHdrPool);
  147. ARP_ZEROSTRUCT(pHdrPool);
  148. EXIT()
  149. }
  150. PNDIS_BUFFER
  151. arpAllocateConstBuffer(
  152. ARP_CONST_BUFFER_POOL *pHdrPool
  153. )
  154. /*++
  155. Routine Description:
  156. HOT PATH
  157. Allocate and return a pre-initialized buffer from the the
  158. specified const buffer pool.
  159. Arguments:
  160. pHdrPool header pool from which buffer is to be allocated.
  161. Return Value:
  162. Non-NULL ptr to buffer on success
  163. NULL on failure (typically because the number of allocated buffers
  164. equals the maximum specified when the header pool was initialized)
  165. --*/
  166. {
  167. ENTER("arpAllocateConstBuffer", 0x52765841)
  168. PNDIS_BUFFER pNdisBuffer;
  169. SLIST_ENTRY * pListEntry;
  170. // Try to pick up a buffer from our list of pre-initialized
  171. // buffers
  172. //
  173. pListEntry = ExInterlockedPopEntrySList(
  174. &pHdrPool->BufferList,
  175. &pHdrPool->NdisLock.SpinLock
  176. );
  177. if (pListEntry != NULL)
  178. {
  179. LONG l;
  180. //
  181. // FAST PATH
  182. //
  183. pNdisBuffer = STRUCT_OF(NDIS_BUFFER, pListEntry, Next);
  184. NDIS_BUFFER_LINKAGE(pNdisBuffer) = NULL;
  185. l = NdisInterlockedDecrement(&pHdrPool->NumInCache);
  186. ASSERT(l>=0);
  187. #define LOGBUFSTATS_TotCachedAllocs(_pHdrPool) \
  188. NdisInterlockedIncrement(&(_pHdrPool)->stats.TotCacheAllocs);
  189. LOGBUFSTATS_TotCachedAllocs(pHdrPool);
  190. }
  191. else
  192. {
  193. //
  194. // SLOW PATH -- allocate a fresh buffer
  195. //
  196. if (pHdrPool->NumAllocd >= pHdrPool->MaxBuffers)
  197. {
  198. //
  199. // Exceeded limit, we won't bother trying to allocate a new ndis buffer.
  200. // (The MaxBuffers limit is hard for us, even if it's not for
  201. // NdisAllocateBufferPool :-) ).
  202. //
  203. // Note that the above check is an approximate check, given that
  204. // many threads may be concurrently making it.
  205. //
  206. #define LOGBUFSTATS_TotAllocFails(_pHdrPool) \
  207. NdisInterlockedIncrement(&(_pHdrPool)->stats.TotAllocFails);
  208. LOGBUFSTATS_TotAllocFails(pHdrPool);
  209. pNdisBuffer = NULL;
  210. }
  211. else
  212. {
  213. NDIS_STATUS Status;
  214. //
  215. // Allocate and initialize a buffer.
  216. //
  217. NdisAllocateBuffer(
  218. &Status,
  219. &pNdisBuffer,
  220. pHdrPool->NdisHandle,
  221. (PVOID) pHdrPool->pvMem,
  222. pHdrPool->cbMem
  223. );
  224. //
  225. // TODO: consider conditionally-compiling stats gathering.
  226. //
  227. if (FAIL(Status))
  228. {
  229. TR_WARN(
  230. ("NdisAllocateBuffer failed: pObj 0x%p, status 0x%x\n",
  231. pHdrPool->pOwningObject, Status));
  232. LOGBUFSTATS_TotAllocFails(pHdrPool);
  233. pNdisBuffer = NULL;
  234. }
  235. else
  236. {
  237. #define LOGBUFSTATS_TotBufAllocs(_pHdrPool) \
  238. NdisInterlockedIncrement(&(_pHdrPool)->stats.TotBufAllocs);
  239. LOGBUFSTATS_TotBufAllocs(pHdrPool);
  240. NdisInterlockedIncrement(&pHdrPool->NumAllocd);
  241. }
  242. }
  243. }
  244. return pNdisBuffer;
  245. }
  246. VOID
  247. arpDeallocateConstBuffer(
  248. ARP_CONST_BUFFER_POOL * pHdrPool,
  249. PNDIS_BUFFER pNdisBuffer
  250. )
  251. /*++
  252. Routine Description:
  253. HOT PATH
  254. Free a buffer previously allocated by a call to arpAllocateConstBuffer.
  255. Arguments:
  256. pHdrPool header pool from which buffer is to be allocated.
  257. pNdisBuffer buffer to free.
  258. --*/
  259. {
  260. ENTER("arpDeallocateConstBuffer", 0x8a905115)
  261. // Try to pick up a pre-initialized buffer from our list of pre-initialized
  262. // buffers
  263. //
  264. if (pHdrPool->NumInCache < pHdrPool->NumBuffersToCache)
  265. {
  266. //
  267. // FAST PATH
  268. //
  269. // Note that the above check is an approximate check, given that
  270. // many threads may be concurrently making it.
  271. //
  272. ExInterlockedPushEntrySList(
  273. &pHdrPool->BufferList,
  274. STRUCT_OF(SLIST_ENTRY, &(pNdisBuffer->Next), Next),
  275. &(pHdrPool->NdisLock.SpinLock)
  276. );
  277. NdisInterlockedIncrement(&pHdrPool->NumInCache);
  278. }
  279. else
  280. {
  281. LONG l;
  282. //
  283. // SLOW PATH -- free back to buffer pool
  284. //
  285. NDIS_BUFFER_LINKAGE(pNdisBuffer) = NULL;
  286. NdisFreeBuffer(pNdisBuffer);
  287. l = NdisInterlockedDecrement(&pHdrPool->NumAllocd);
  288. ASSERT(l>=0);
  289. }
  290. }