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.

505 lines
10 KiB

  1. #include "brfprv.h"
  2. //========== Memory Management =============================================
  3. #ifndef WIN32
  4. #define MAX_WORD 0xffff
  5. DECLARE_HANDLE(HHEAP);
  6. typedef struct { // maps to the bottom of a 16bit DS
  7. WORD reserved[8];
  8. WORD cAlloc;
  9. WORD cbAllocFailed;
  10. HHEAP hhpFirst;
  11. HHEAP hhpNext;
  12. } HEAP;
  13. #define PHEAP(hhp) ((HEAP *)MAKELP(hhp, 0))
  14. #define MAKEHP(sel, off) ((void _huge*)MAKELP((sel), (off)))
  15. #define CBSUBALLOCMAX 0x0000f000L
  16. HHEAP g_hhpFirst = NULL;
  17. BOOL DestroyHeap(HHEAP hhp);
  18. void Mem_Terminate()
  19. {
  20. while (g_hhpFirst)
  21. DestroyHeap(g_hhpFirst);
  22. }
  23. BOOL CreateHeap(WORD cbInitial)
  24. {
  25. HHEAP hhp;
  26. if (cbInitial < 1024)
  27. cbInitial = 1024;
  28. hhp = (HHEAP)GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT | GMEM_SHARE, cbInitial);
  29. if (!hhp)
  30. return FALSE;
  31. if (!LocalInit((WORD)hhp, sizeof(HEAP), cbInitial - 1))
  32. {
  33. GlobalFree(hhp);
  34. return FALSE;
  35. }
  36. PHEAP(hhp)->cAlloc = 0;
  37. PHEAP(hhp)->cbAllocFailed = MAX_WORD;
  38. PHEAP(hhp)->hhpNext = g_hhpFirst;
  39. g_hhpFirst = hhp;
  40. DebugMsg(DM_TRACE, TEXT("CreateHeap: added new local heap %x"), hhp);
  41. return TRUE;
  42. }
  43. #pragma optimize("o", off) // linked list removals don't optimize correctly
  44. BOOL DestroyHeap(HHEAP hhp)
  45. {
  46. ASSERT(hhp);
  47. ASSERT(g_hhpFirst);
  48. if (g_hhpFirst == hhp)
  49. {
  50. g_hhpFirst = PHEAP(hhp)->hhpNext;
  51. }
  52. else
  53. {
  54. HHEAP hhpT = g_hhpFirst;
  55. while (PHEAP(hhpT)->hhpNext != hhp)
  56. {
  57. hhpT = PHEAP(hhpT)->hhpNext;
  58. if (!hhpT)
  59. return FALSE;
  60. }
  61. PHEAP(hhpT)->hhpNext = PHEAP(hhp)->hhpNext;
  62. }
  63. if (GlobalFree((HGLOBAL)hhp) != NULL)
  64. return FALSE;
  65. return TRUE;
  66. }
  67. #pragma optimize("", on) // back to default optimizations
  68. #pragma optimize("lge", off) // Suppress warnings associated with use of _asm...
  69. void * HeapAlloc(HHEAP hhp, WORD cb)
  70. {
  71. void * pb;
  72. _asm {
  73. push ds
  74. mov ds,hhp
  75. }
  76. pb = (void *)LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, cb);
  77. if (pb)
  78. ((HEAP *)0)->cAlloc++;
  79. _asm {
  80. pop ds
  81. }
  82. return pb;
  83. }
  84. #pragma optimize("o", off) // linked list removals don't optimize correctly
  85. void _huge* WINAPI SharedAlloc(long cb)
  86. {
  87. void * pb;
  88. HHEAP hhp;
  89. HHEAP hhpPrev;
  90. // If this is a big allocation, just do a global alloc.
  91. //
  92. if (cb > CBSUBALLOCMAX)
  93. {
  94. void * lpb = MAKEHP(GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT | GMEM_SHARE, cb), 0);
  95. if (!lpb)
  96. DebugMsg(DM_ERROR, TEXT("Alloc: out of memory"));
  97. return lpb;
  98. }
  99. hhp = g_hhpFirst;
  100. while (TRUE)
  101. {
  102. if (hhp == NULL)
  103. {
  104. if (!CreateHeap(0))
  105. {
  106. DebugMsg(DM_ERROR, TEXT("Alloc: out of memory"));
  107. return NULL;
  108. }
  109. hhp = g_hhpFirst;
  110. }
  111. pb = HeapAlloc(hhp, (WORD)cb);
  112. if (pb)
  113. return MAKEHP(hhp, pb);
  114. // Record the size of the allocation that failed.
  115. // Later attempts to allocate more than this amount
  116. // will not succeed. This gets reset anytime anything
  117. // is freed in the heap.
  118. //
  119. PHEAP(hhp)->cbAllocFailed = (WORD)cb;
  120. // First heap is full... see if there's room in any other heap...
  121. //
  122. for (hhpPrev = hhp; hhp = PHEAP(hhp)->hhpNext; hhpPrev = hhp)
  123. {
  124. // If the last allocation to fail in this heap
  125. // is not larger than cb, don't even try an allocation.
  126. //
  127. if ((WORD)cb >= PHEAP(hhp)->cbAllocFailed)
  128. continue;
  129. pb = HeapAlloc(hhp, (WORD)cb);
  130. if (pb)
  131. {
  132. // This heap had room: move it to the front...
  133. //
  134. PHEAP(hhpPrev)->hhpNext = PHEAP(hhp)->hhpNext;
  135. PHEAP(hhp)->hhpNext = g_hhpFirst;
  136. g_hhpFirst = hhp;
  137. return MAKEHP(hhp, pb);
  138. }
  139. else
  140. {
  141. // The alloc failed. Set cbAllocFailed...
  142. //
  143. PHEAP(hhp)->cbAllocFailed = (WORD)cb;
  144. }
  145. }
  146. }
  147. }
  148. #pragma optimize("", on) // back to default optimizations
  149. #pragma optimize("lge", off) // Suppress warnings associated with use of _asm...
  150. void _huge* WINAPI SharedReAlloc(void _huge* pb, long cb)
  151. {
  152. void * pbNew;
  153. void _huge* lpbNew;
  154. UINT cbOld;
  155. // FEATURE, does not work with cb > 64k
  156. if (!pb)
  157. return SharedAlloc(cb);
  158. if (OFFSETOF(pb) == 0)
  159. return MAKEHP(GlobalReAlloc((HGLOBAL)SELECTOROF(pb), cb, GMEM_MOVEABLE | GMEM_ZEROINIT), 0);
  160. _asm {
  161. push ds
  162. mov ds,word ptr [pb+2]
  163. }
  164. pbNew = (void *)LocalReAlloc((HLOCAL)OFFSETOF(pb), (int)cb, LMEM_MOVEABLE | LMEM_ZEROINIT);
  165. if (!pbNew)
  166. cbOld = LocalSize((HLOCAL)OFFSETOF(pb));
  167. _asm {
  168. pop ds
  169. }
  170. if (pbNew)
  171. return MAKEHP(SELECTOROF(pb), pbNew);
  172. lpbNew = SharedAlloc(cb);
  173. if (lpbNew)
  174. {
  175. hmemcpy((void *)lpbNew, (void *)pb, cbOld);
  176. Free(pb);
  177. }
  178. else
  179. {
  180. DebugMsg(DM_ERROR, TEXT("ReAlloc: out of memory"));
  181. }
  182. return lpbNew;
  183. }
  184. BOOL WINAPI SharedFree(void _huge* * ppb)
  185. {
  186. BOOL fSuccess;
  187. UINT cAlloc;
  188. void _huge * pb = *ppb;
  189. if (!pb)
  190. return FALSE;
  191. *ppb = 0;
  192. if (OFFSETOF(pb) == 0)
  193. return (GlobalFree((HGLOBAL)SELECTOROF(pb)) == NULL);
  194. _asm {
  195. push ds
  196. mov ds,word ptr [pb+2]
  197. }
  198. fSuccess = (LocalFree((HLOCAL)OFFSETOF(pb)) ? FALSE : TRUE);
  199. cAlloc = 1;
  200. if (fSuccess)
  201. {
  202. cAlloc = --((HEAP *)0)->cAlloc;
  203. ((HEAP *)0)->cbAllocFailed = MAX_WORD;
  204. }
  205. _asm {
  206. pop ds
  207. }
  208. if (cAlloc == 0)
  209. DestroyHeap((HHEAP)SELECTOROF(pb));
  210. return fSuccess;
  211. }
  212. DWORD WINAPI SharedGetSize(void _huge* pb)
  213. {
  214. WORD wSize;
  215. if (OFFSETOF(pb) == 0)
  216. return GlobalSize((HGLOBAL)SELECTOROF(pb));
  217. _asm {
  218. push ds
  219. mov ds,word ptr [pb+2]
  220. }
  221. wSize = LocalSize((HLOCAL)OFFSETOF(pb));
  222. _asm {
  223. pop ds
  224. }
  225. return (DWORD)wSize;
  226. }
  227. #if 0
  228. // hmemcpy() is faster (says davidds)
  229. void WINAPI MemCopy(void * pTo, const void * pFrom, UINT cb)
  230. {
  231. _asm {
  232. mov cx,cb
  233. jcxz mcexit
  234. ;; push si
  235. ;; push di
  236. mov dx,ds
  237. lds si,pFrom
  238. les di,pTo
  239. cmp si,di
  240. jae mccopyup
  241. mov ax,cx
  242. dec ax
  243. dec ax
  244. add si,ax
  245. add di,ax
  246. std
  247. shr cx,1
  248. rep movsw
  249. jnc mc100
  250. inc si
  251. inc di
  252. movsb
  253. mc100:
  254. cld
  255. jmp short mcexit
  256. mccopyup:
  257. cld
  258. shr cx,1
  259. rep movsw
  260. jnc mc200
  261. movsb
  262. mc200:
  263. mcexit:
  264. mov ds,dx
  265. ;; pop di
  266. ;; pop si
  267. }
  268. }
  269. #endif
  270. #pragma optimize("", on)
  271. #else // WIN32
  272. // Define a Global Shared Heap that we use allocate memory out of that we
  273. // Need to share between multiple instances.
  274. HANDLE g_hSharedHeap = NULL;
  275. #define MAXHEAPSIZE 2097152
  276. #define HEAP_SHARED 0x04000000 /* put heap in shared memory */
  277. //----------------------------------------------------------------------------
  278. void PUBLIC Mem_Terminate()
  279. {
  280. // Assuming that everything else has exited
  281. //
  282. if (g_hSharedHeap != NULL)
  283. HeapDestroy(g_hSharedHeap);
  284. g_hSharedHeap = NULL;
  285. }
  286. //----------------------------------------------------------------------------
  287. void * WINAPI SharedAlloc(long cb)
  288. {
  289. // I will assume that this is the only one that needs the checks to
  290. // see if the heap has been previously created or not
  291. if (g_hSharedHeap == NULL)
  292. {
  293. ENTEREXCLUSIVE();
  294. if (g_hSharedHeap == NULL)
  295. {
  296. g_hSharedHeap = HeapCreate(0, 1, MAXHEAPSIZE);
  297. }
  298. LEAVEEXCLUSIVE();
  299. // If still NULL we have problems!
  300. if (g_hSharedHeap == NULL)
  301. return(NULL);
  302. }
  303. return HeapAlloc(g_hSharedHeap, HEAP_ZERO_MEMORY, cb);
  304. }
  305. //----------------------------------------------------------------------------
  306. void * WINAPI SharedReAlloc(void * pb, long cb)
  307. {
  308. if (pb==NULL)
  309. {
  310. return SharedAlloc(cb);
  311. }
  312. return HeapReAlloc(g_hSharedHeap, HEAP_ZERO_MEMORY, pb, cb);
  313. }
  314. //----------------------------------------------------------------------------
  315. BOOL WINAPI SharedFree(void ** ppb)
  316. {
  317. void * pb = *ppb;
  318. if (!pb)
  319. return FALSE;
  320. *ppb = 0;
  321. return HeapFree(g_hSharedHeap, 0, pb);
  322. }
  323. //----------------------------------------------------------------------------
  324. DWORD WINAPI SharedGetSize(void * pb)
  325. {
  326. return (DWORD)HeapSize(g_hSharedHeap, 0, pb);
  327. }
  328. //----------------------------------------------------------------------------
  329. // The following functions are for debug only and are used to try to
  330. // calculate memory usage.
  331. //
  332. #ifdef DEBUG
  333. typedef struct _HEAPTRACE
  334. {
  335. DWORD cAlloc;
  336. DWORD cFailure;
  337. DWORD cReAlloc;
  338. DWORD cbMaxTotal;
  339. DWORD cCurAlloc;
  340. DWORD cbCurTotal;
  341. } HEAPTRACE;
  342. HEAPTRACE g_htSync = {0}; // Start of zero...
  343. LPVOID WINAPI MemAlloc(HANDLE hheap, DWORD cb)
  344. {
  345. LPVOID lp;
  346. lp = HeapAlloc(hheap, HEAP_ZERO_MEMORY, cb);
  347. if (lp == NULL)
  348. {
  349. g_htSync.cFailure++;
  350. return NULL;
  351. }
  352. // Update counts.
  353. g_htSync.cAlloc++;
  354. g_htSync.cCurAlloc++;
  355. g_htSync.cbCurTotal += cb;
  356. if (g_htSync.cbCurTotal > g_htSync.cbMaxTotal)
  357. g_htSync.cbMaxTotal = g_htSync.cbCurTotal;
  358. return lp;
  359. }
  360. LPVOID WINAPI MemReAlloc(HANDLE hheap, LPVOID pb, DWORD cb)
  361. {
  362. LPVOID lp;
  363. DWORD cbOld;
  364. cbOld = HeapSize(hheap, 0, pb);
  365. lp = HeapReAlloc(hheap, HEAP_ZERO_MEMORY, pb,cb);
  366. if (lp == NULL)
  367. {
  368. g_htSync.cFailure++;
  369. return NULL;
  370. }
  371. // Update counts.
  372. g_htSync.cReAlloc++;
  373. g_htSync.cbCurTotal += cb - cbOld;
  374. if (g_htSync.cbCurTotal > g_htSync.cbMaxTotal)
  375. g_htSync.cbMaxTotal = g_htSync.cbCurTotal;
  376. return lp;
  377. }
  378. BOOL WINAPI MemFree(HANDLE hheap, LPVOID pb)
  379. {
  380. BOOL fRet;
  381. DWORD cbOld;
  382. cbOld = HeapSize(hheap, 0, pb);
  383. fRet = HeapFree(hheap, 0, pb);
  384. if (fRet)
  385. {
  386. // Update counts.
  387. g_htSync.cCurAlloc--;
  388. g_htSync.cbCurTotal -= cbOld;
  389. }
  390. return(fRet);
  391. }
  392. DWORD WINAPI MemSize(HANDLE hheap, LPVOID pb)
  393. {
  394. return HeapSize(hheap, 0, pb);
  395. }
  396. #endif
  397. #endif // WIN32