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.

379 lines
9.7 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1995 - 2000 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: FPM.cpp
  6. * Content: fixed size pool manager
  7. *
  8. * History:
  9. * Date By Reason
  10. * ====== == ======
  11. * 12-18-97 aarono Original
  12. * 11-06-98 ejs Add custom handler for Release function
  13. * 04-12-99 jtk Trimmed unused functions and parameters, added size assert
  14. * 11-22-99 jtk Converted to .CPP
  15. * 01-31-2000 jtk Changed to use DNCriticalSections. Added code to check
  16. * for items already being in the pool on Release().
  17. * 04-11-2000 ejs Put ASSERTs back into service. They had been MACRO'd away to nothing
  18. * 11-16/2000 rmt Bug #40587 - DPVOICE: Mixing server needs to use multi-processors
  19. ***************************************************************************/
  20. #include "dncmni.h"
  21. #include "fpm.h"
  22. #define DPMEM_ALLOC DNMalloc
  23. #define DPMEM_FREE DNFree
  24. #define ASSERT(X) DNASSERT(X)
  25. //#define CHECK_FOR_DUPLICATE_FPM_RELEASE
  26. //**********************************************************************
  27. // ------------------------------
  28. // FN_BOOL_DUMMY - place-holder function to return a Boolean
  29. //
  30. // Entry: Pointer
  31. //
  32. // Exit: Boolean
  33. // ------------------------------
  34. #undef DPF_MODNAME
  35. #define DPF_MODNAME "FN_BOOL_DUMMY"
  36. BOOL FN_BOOL_DUMMY(void *pvItem)
  37. {
  38. return TRUE;
  39. }
  40. //**********************************************************************
  41. //**********************************************************************
  42. // ------------------------------
  43. // FN_VOID_DUMMY - place-holder function
  44. //
  45. // Entry: Pointer
  46. //
  47. // Exit: Boolean
  48. // ------------------------------
  49. #undef DPF_MODNAME
  50. #define DPF_MODNAME "FN_VOID_DUMMY"
  51. VOID FN_VOID_DUMMY(void *pvItem)
  52. {
  53. return;
  54. }
  55. //**********************************************************************
  56. //**********************************************************************
  57. // ------------------------------
  58. // FPM_Get - get an item from the pool
  59. //
  60. // Entry: Pointer to pool
  61. //
  62. // Exit: Pointer to item
  63. // NULL = out of memory
  64. // ------------------------------
  65. #undef DPF_MODNAME
  66. #define DPF_MODNAME "FPM_Get"
  67. void * FPM_Get( FPOOL *pPool )
  68. {
  69. void * pvItem;
  70. DNEnterCriticalSection(&pPool->cs);
  71. DNASSERT(pPool->pPoolElements == 0 || !IsBadReadPtr(pPool->pPoolElements, sizeof(PVOID)));
  72. if(!pPool->pPoolElements){
  73. DNLeaveCriticalSection(&pPool->cs);
  74. pvItem = DPMEM_ALLOC(pPool->cbItemSize);
  75. if((pvItem) && !(*pPool->fnBlockInitAlloc)(pvItem) ){
  76. DPMEM_FREE(pvItem);
  77. pvItem=NULL;
  78. }
  79. DNEnterCriticalSection(&pPool->cs);
  80. if(pvItem){
  81. pPool->nAllocated++;
  82. if( pPool->pdwTotalItems )
  83. (*pPool->pdwTotalItems)++;
  84. }
  85. } else {
  86. pvItem=pPool->pPoolElements;
  87. pPool->pPoolElements=*((void **)pvItem);
  88. DNASSERT(pPool->pPoolElements == 0 || !IsBadReadPtr(pPool->pPoolElements, sizeof(PVOID)));
  89. }
  90. if(pvItem){
  91. pPool->nInUse++;
  92. if( pPool->pdwOutstandingItems )
  93. (*pPool->pdwOutstandingItems)++;
  94. DNLeaveCriticalSection(&pPool->cs);
  95. (*pPool->fnBlockInit)(pvItem);
  96. }
  97. else {
  98. DNLeaveCriticalSection(&pPool->cs);
  99. }
  100. return pvItem;
  101. }
  102. //**********************************************************************
  103. //**********************************************************************
  104. // ------------------------------
  105. // FPM_Release - return element to pool
  106. //
  107. // Entry: Pointer to pool
  108. // Pointer to element
  109. //
  110. // Exit: Nothing
  111. // ------------------------------
  112. #undef DPF_MODNAME
  113. #define DPF_MODNAME "FPM_Release"
  114. void FPM_Release( FPOOL *pPool, void *pvItem)
  115. {
  116. (*pPool->fnBlockRelease)(pvItem);
  117. DNEnterCriticalSection(&pPool->cs);
  118. #if defined(CHECK_FOR_DUPLICATE_FPM_RELEASE) && defined(DEBUG)
  119. {
  120. void *pTemp;
  121. pTemp = pPool->pPoolElements;
  122. while ( pTemp != NULL )
  123. {
  124. DNASSERT( pTemp != pvItem );
  125. pTemp = *((void**)pTemp);
  126. }
  127. }
  128. #endif // CHECK_FOR_DUPLICATE_FPM_RELEASE
  129. pPool->nInUse--;
  130. if( pPool->pdwOutstandingItems )
  131. (*pPool->pdwOutstandingItems)--;
  132. #ifdef NO_POOLS
  133. (*pPool->fnBlockFini)(pvItem);
  134. DPMEM_FREE(pvItem);
  135. pPool->nAllocated--;
  136. #else
  137. *((void**)pvItem)=pPool->pPoolElements;
  138. pPool->pPoolElements=pvItem;
  139. #endif
  140. DNASSERT(pPool->pPoolElements == 0 || !IsBadReadPtr(pPool->pPoolElements, sizeof(PVOID)));
  141. DNLeaveCriticalSection(&pPool->cs);
  142. }
  143. //**********************************************************************
  144. //**********************************************************************
  145. // ------------------------------
  146. // FPM_Fini - destroy pool
  147. //
  148. // Entry: Pointer to pool
  149. //
  150. // Exit: Nothing
  151. //
  152. // Note: This function frees the pool memory, the pointer passed in is
  153. // then invalid!
  154. // ------------------------------
  155. #undef DPF_MODNAME
  156. #define DPF_MODNAME "FPM_Fini"
  157. VOID FPM_Fini( FPOOL *pPool, BOOL fAssertOnLeak )
  158. {
  159. FPM_Deinitialize( pPool, fAssertOnLeak );
  160. DPMEM_FREE( pPool );
  161. }
  162. //**********************************************************************
  163. //**********************************************************************
  164. // ------------------------------
  165. // FPM_Deinitialize - deinitialize pool
  166. //
  167. // Entry: Pointer to pool
  168. // Boolean to control if it should assert on a leak
  169. //
  170. // Exit: Nothing
  171. // ------------------------------
  172. #undef DPF_MODNAME
  173. #define DPF_MODNAME "FPM_Deinitialize"
  174. VOID FPM_Deinitialize( FPOOL *pPool, BOOL fAssertOnLeak )
  175. {
  176. void *pvItem;
  177. while(pPool->pPoolElements){
  178. pvItem = pPool->pPoolElements;
  179. pPool->pPoolElements=*((void **)pvItem);
  180. DNASSERT(pPool->pPoolElements == 0 || !IsBadReadPtr(pPool->pPoolElements, sizeof(PVOID)));
  181. (*pPool->fnBlockFini)(pvItem);
  182. DPMEM_FREE(pvItem);
  183. pPool->nAllocated--;
  184. if( pPool->pdwOutstandingItems )
  185. (*pPool->pdwOutstandingItems)--;
  186. }
  187. if( fAssertOnLeak )
  188. {
  189. if(pPool->nAllocated){
  190. ASSERT(0);
  191. }
  192. }
  193. DNDeleteCriticalSection(&pPool->cs);
  194. }
  195. //**********************************************************************
  196. //**********************************************************************
  197. // ------------------------------
  198. // FPM_Create - Allocate a new pool
  199. //
  200. // Entry: Size of pool element
  201. // Pointer to function for initializing element on alloc
  202. // Pointer to function for initializing element on get
  203. // Pointer to function for deinitializing element on release
  204. // Pointer to function for deinitializing element on free
  205. //
  206. // Exit: Pointer to new pool
  207. // NULL = out of memory
  208. // ------------------------------
  209. #undef DPF_MODNAME
  210. #define DPF_MODNAME "FPM_Create"
  211. FPOOL *FPM_Create( unsigned int size,
  212. FN_BLOCKINITALLOC fnBlockInitAlloc,
  213. FN_BLOCKINIT fnBlockInit,
  214. FN_BLOCKRELEASE fnBlockRelease,
  215. FN_BLOCKFINI fnBlockFini,
  216. DWORD *pdwOutstandingItems,
  217. DWORD *pdwTotalItems
  218. )
  219. {
  220. LPFPOOL pPool;
  221. pPool=static_cast<FPOOL*>( DPMEM_ALLOC( sizeof( *pPool ) ) );
  222. if ( pPool == NULL )
  223. {
  224. return NULL;
  225. }
  226. if ( FPM_Initialize( pPool, // pointer to fixed pool
  227. size, // size of pool element
  228. fnBlockInitAlloc, // pointer to function for initializing element on alloc
  229. fnBlockInit, // pointer to function for initializing element on get
  230. fnBlockRelease, // pointer to function for deinitializing element on release
  231. fnBlockFini, // pointer to function for deinitializing element on free
  232. pdwOutstandingItems,
  233. pdwTotalItems
  234. ) == FALSE )
  235. {
  236. DPMEM_FREE( pPool );
  237. pPool = NULL;
  238. }
  239. return pPool;
  240. }
  241. //**********************************************************************
  242. //**********************************************************************
  243. // ------------------------------
  244. // FPM_Initialize - initialize an instance of a pool
  245. //
  246. // Entry: Pointer to pool
  247. // Size of pool element
  248. // Pointer to function for initializing element on alloc
  249. // Pointer to function for initializing element on get
  250. // Pointer to function for deinitializing element on release
  251. // Pointer to function for deinitializing element on free
  252. //
  253. // Exit: Boolean indicating success
  254. // TRUE = success
  255. // FALSE = failure
  256. // ------------------------------
  257. #undef DPF_MODNAME
  258. #define DPF_MODNAME "FPM_Initialize"
  259. BOOL FPM_Initialize( LPFPOOL pPool, // pointer to pool to initialize
  260. DWORD dwElementSize, // size of blocks in pool
  261. FN_BLOCKINITALLOC fnBlockInitAlloc, // fn called for each new alloc
  262. FN_BLOCKINIT fnBlockInit, // fn called each time block used
  263. FN_BLOCKRELEASE fnBlockRelease, // fn called each time block released
  264. FN_BLOCKFINI fnBlockFini, // fn called before releasing mem
  265. DWORD *pdwOutstandingItems,
  266. DWORD *pdwTotalItems
  267. )
  268. {
  269. BOOL fReturn;
  270. fReturn = TRUE;
  271. if ( DNInitializeCriticalSection(&pPool->cs) == FALSE )
  272. {
  273. fReturn = FALSE;
  274. goto Exit;
  275. }
  276. DebugSetCriticalSectionRecursionCount( &pPool->cs, 0 );
  277. pPool->pPoolElements = NULL;
  278. pPool->nAllocated = 0;
  279. pPool->nInUse = 0;
  280. pPool->pdwOutstandingItems = pdwOutstandingItems;
  281. pPool->pdwTotalItems = pdwTotalItems;
  282. if( pPool->pdwOutstandingItems )
  283. *(pPool->pdwOutstandingItems) = 0;
  284. if( pPool->pdwTotalItems )
  285. *(pPool->pdwTotalItems) = 0;
  286. if(fnBlockInitAlloc){
  287. pPool->fnBlockInitAlloc = fnBlockInitAlloc;
  288. } else {
  289. pPool->fnBlockInitAlloc = FN_BOOL_DUMMY;
  290. }
  291. if(fnBlockInit){
  292. pPool->fnBlockInit = fnBlockInit;
  293. } else {
  294. pPool->fnBlockInit = FN_VOID_DUMMY;
  295. }
  296. if(fnBlockRelease){
  297. pPool->fnBlockRelease = fnBlockRelease;
  298. } else {
  299. pPool->fnBlockRelease = FN_VOID_DUMMY;
  300. }
  301. if(fnBlockFini){
  302. pPool->fnBlockFini = fnBlockFini;
  303. } else {
  304. pPool->fnBlockFini = FN_VOID_DUMMY;
  305. }
  306. pPool->Get = FPM_Get;
  307. pPool->Release= FPM_Release;
  308. pPool->Fini = FPM_Fini;
  309. // FPM reuses the item memory as a linked list when not in use,
  310. // make sure the items are large enough
  311. ASSERT( dwElementSize >= sizeof( void* ) );
  312. pPool->cbItemSize = dwElementSize;
  313. Exit:
  314. return fReturn;
  315. }
  316. //**********************************************************************