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.

229 lines
5.3 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. utilmemf.cxx
  5. Abstract:
  6. Miscellaneous useful utilities
  7. Author:
  8. Sergey Solyanik (SergeyS)
  9. --*/
  10. #include "pch.h"
  11. #pragma hdrstop
  12. #include <svsutil.hxx>
  13. //
  14. // Fixed memory sector
  15. //
  16. struct FixedMemList
  17. {
  18. union
  19. {
  20. unsigned char ucaPlaceholder[SVSUTIL_MAX_ALIGNMENT];
  21. struct FixedMemList *pfmlNext;
  22. } u;
  23. unsigned char bData[1];
  24. };
  25. struct FixedMemDescr
  26. {
  27. void **ppvFreeList;
  28. FixedMemList *pfml;
  29. CRITICAL_SECTION *pcs;
  30. unsigned int uiBlockSize;
  31. unsigned int uiBlockIncr;
  32. unsigned int uiListSize;
  33. };
  34. FixedMemDescr *svsutil_AllocFixedMemDescr (unsigned int a_uiBlockSize, unsigned int a_uiBlockIncr) {
  35. SVSUTIL_ASSERT (a_uiBlockSize);
  36. SVSUTIL_ASSERT (a_uiBlockIncr);
  37. if (a_uiBlockSize < sizeof(void *))
  38. a_uiBlockSize = sizeof (void *);
  39. FixedMemDescr *pfmd = (FixedMemDescr *)g_funcAlloc (sizeof(FixedMemDescr), g_pvAllocData);
  40. if (! pfmd)
  41. return NULL;
  42. pfmd->ppvFreeList = NULL;
  43. pfmd->pfml = NULL;
  44. pfmd->pcs = NULL;
  45. pfmd->uiBlockSize = a_uiBlockSize;
  46. pfmd->uiBlockIncr = a_uiBlockIncr;
  47. pfmd->uiListSize = offsetof (FixedMemList, bData) + a_uiBlockSize * a_uiBlockIncr;
  48. return pfmd;
  49. }
  50. FixedMemDescr *svsutil_AllocFixedMemDescrSynch (unsigned int a_uiBlockSize, unsigned int a_uiBlockIncr, CRITICAL_SECTION *a_pcs) {
  51. SVSUTIL_ASSERT (a_uiBlockSize);
  52. SVSUTIL_ASSERT (a_uiBlockIncr);
  53. SVSUTIL_ASSERT (a_pcs);
  54. if (a_uiBlockSize < sizeof(void *))
  55. a_uiBlockSize = sizeof (void *);
  56. FixedMemDescr *pfmd = (FixedMemDescr *)g_funcAlloc (sizeof(FixedMemDescr), g_pvAllocData);
  57. if (! pfmd)
  58. return NULL;
  59. pfmd->ppvFreeList = NULL;
  60. pfmd->pfml = NULL;
  61. pfmd->pcs = a_pcs;
  62. pfmd->uiBlockSize = a_uiBlockSize;
  63. pfmd->uiBlockIncr = a_uiBlockIncr;
  64. pfmd->uiListSize = offsetof (FixedMemList, bData) + a_uiBlockSize * a_uiBlockIncr;
  65. return pfmd;
  66. }
  67. int svsutil_IsFixedEmpty (FixedMemDescr *a_pfmd) {
  68. return a_pfmd->pfml == NULL;
  69. }
  70. int svsutil_FixedBlockSize (FixedMemDescr *a_pfmd) {
  71. return a_pfmd->uiBlockSize;
  72. }
  73. void *svsutil_GetFixed (FixedMemDescr *a_pfmd) {
  74. if (a_pfmd->pcs)
  75. EnterCriticalSection (a_pfmd->pcs);
  76. if (! a_pfmd->ppvFreeList)
  77. {
  78. FixedMemList *pfml = (FixedMemList *)g_funcAlloc (a_pfmd->uiListSize, g_pvAllocData);
  79. pfml->u.pfmlNext = a_pfmd->pfml;
  80. a_pfmd->pfml = pfml;
  81. a_pfmd->ppvFreeList = (void **)&pfml->bData[0];
  82. unsigned char *pucRunner = (unsigned char *)a_pfmd->ppvFreeList;
  83. unsigned char *pucEndRun = ((unsigned char *)pfml) + a_pfmd->uiListSize;
  84. for ( ; ; )
  85. {
  86. unsigned char *pucRunnerNext = pucRunner + a_pfmd->uiBlockSize;
  87. if (pucRunnerNext >= pucEndRun)
  88. {
  89. *(void **)pucRunner = NULL;
  90. break;
  91. }
  92. *(void **)pucRunner = (void *)pucRunnerNext;
  93. pucRunner = pucRunnerNext;
  94. }
  95. }
  96. void *pvPtr = (void *)a_pfmd->ppvFreeList;
  97. a_pfmd->ppvFreeList = (void **)*a_pfmd->ppvFreeList;
  98. if (a_pfmd->pcs)
  99. LeaveCriticalSection (a_pfmd->pcs);
  100. return pvPtr;
  101. }
  102. void svsutil_FreeFixed (void *pvData, FixedMemDescr *a_pfmd) {
  103. if (a_pfmd->pcs)
  104. EnterCriticalSection (a_pfmd->pcs);
  105. #if defined (SVSUTIL_DEBUG_HEAP)
  106. void **ppvFreeList = a_pfmd->ppvFreeList;
  107. while (ppvFreeList)
  108. {
  109. SVSUTIL_ASSERT(pvData != ppvFreeList); // Otherwise has already been freed
  110. ppvFreeList = (void **)*ppvFreeList;
  111. }
  112. FixedMemList *pfml = a_pfmd->pfml;
  113. while (pfml)
  114. {
  115. if ((pvData > pfml) && (pvData < ((unsigned char *)pfml + a_pfmd->uiListSize)))
  116. break;
  117. pfml = pfml->u.pfmlNext;
  118. }
  119. SVSUTIL_ASSERT (pfml); // Otherwise not part of any block!
  120. memset (pvData, 0xff, a_pfmd->uiBlockSize);
  121. #endif
  122. *(void **)pvData = (void *)a_pfmd->ppvFreeList;
  123. a_pfmd->ppvFreeList = (void **)pvData;
  124. if (a_pfmd->pcs)
  125. LeaveCriticalSection (a_pfmd->pcs);
  126. }
  127. void svsutil_ReleaseFixedNonEmpty (FixedMemDescr *a_pfmd) {
  128. if (a_pfmd->pcs)
  129. EnterCriticalSection (a_pfmd->pcs);
  130. FixedMemList *pfml = a_pfmd->pfml;
  131. while (pfml)
  132. {
  133. FixedMemList *pfmlNext = pfml->u.pfmlNext;
  134. g_funcFree (pfml, g_pvFreeData);
  135. pfml = pfmlNext;
  136. }
  137. if (a_pfmd->pcs)
  138. LeaveCriticalSection (a_pfmd->pcs);
  139. g_funcFree (a_pfmd, g_pvFreeData);
  140. }
  141. void svsutil_ReleaseFixedEmpty (FixedMemDescr *a_pfmd) {
  142. if (a_pfmd->pcs)
  143. EnterCriticalSection (a_pfmd->pcs);
  144. #if defined (SVSUTIL_DEBUG_HEAP)
  145. unsigned int uiBlockCount = 0;
  146. void **ppvRunner = a_pfmd->ppvFreeList;
  147. while (ppvRunner)
  148. {
  149. ++uiBlockCount;
  150. ppvRunner = (void **)*ppvRunner;
  151. }
  152. unsigned int uiBlockCount2 = 0;
  153. FixedMemList *pfmlRunner = a_pfmd->pfml;
  154. while (pfmlRunner)
  155. {
  156. uiBlockCount2 += a_pfmd->uiBlockIncr;
  157. pfmlRunner = pfmlRunner->u.pfmlNext;
  158. }
  159. SVSUTIL_ASSERT (uiBlockCount == uiBlockCount2);
  160. #endif
  161. if (a_pfmd->pcs)
  162. LeaveCriticalSection (a_pfmd->pcs);
  163. svsutil_ReleaseFixedNonEmpty (a_pfmd);
  164. }