source: trunk/src/kernel32/os2heap.cpp

Last change on this file was 21932, checked in by dmik, 14 years ago

kernel32: More logging.

File size: 12.7 KB
RevLine 
[8877]1/* $Id: os2heap.cpp,v 1.33 2002-07-15 14:28:51 sandervl Exp $ */
[99]2
[4]3/*
4 * Heap class for OS/2
5 *
[7728]6 * Copyright 1998-2002 Sander van Leeuwen <sandervl@xs4all.nl>
[4]7 *
[46]8 *
[8877]9 * NOTE: Do NOT use high memory here. Risky with 16 bits tcpip stack
10 * If this is ever changed, then you must use VirtualAlloc!
11 *
[1104]12 * NOTE: ReAlloc allocates memory using Alloc if memory pointer == NULL
[1770]13 * WINE controls depend on this, even though it apparently
[1104]14 * doesn't work like this in Windows.
[7728]15 * NOTE: Round up size to next 8 bytes boundary
16 * When reallocating memory block, don't use different
17 * memory block unless new size is larger than old size
18 * (rounded up to next 8 bytes boundary)
19 * (Verified this behaviour in NT4 (Global/Heap(Re)Alloc);
20 * fixes crashes in Opera 5.12 which relies on this 'feature')
[1104]21 *
[46]22 * Project Odin Software License can be found in LICENSE.TXT
23 *
[4]24 */
25#define INCL_DOSMEMMGR
26#define INCL_DOSSEMAPHORES
27#define INCL_DOSERRORS
[120]28#include <os2wrap.h> //Odin32 OS/2 api wrappers
[4]29#include <stdlib.h>
30#include <string.h>
[6354]31#include <umalloc.h>
[461]32
[4]33#include "win32type.h"
34#include "os2heap.h"
35#include "misc.h"
36#include "vmutex.h"
[1770]37#include "initterm.h"
[3464]38#include <odin32validate.h>
[4]39
[2803]40#define DBG_LOCALLOG DBG_os2heap
41#include "dbglocal.h"
42
[21302]43#include <_ras.h>
44
45#ifdef RAS
46RAS_TRACK_HANDLE rthHeap = 0;
47#endif
48
[4]49#ifndef HEAP_NO_SERIALIZE
50 #define HEAP_NO_SERIALIZE 1
51#endif
52
53#ifndef HEAP_ZERO_MEMORY
54 #define HEAP_ZERO_MEMORY 8
55#endif
56
[6354]57void * _LNK_CONV getmoreHeapMem(Heap_t pHeap, size_t *size, int *clean);
[6954]58void _LNK_CONV releaseHeapMem(Heap_t pHeap, void *block, size_t size);
[6354]59
[7360]60VMutex heaplistmutex; //protects linked lists of heaps
[7027]61
[7360]62
[4]63//******************************************************************************
[7027]64// Fast Heap Handle Management
[4]65//******************************************************************************
[7027]66
[7358]67HANDLE fhhm_lastHandle = 0;
68OS2Heap* fhhm_lastHeap = NULL;
[7027]69
70
71//******************************************************************************
72//******************************************************************************
[6397]73OS2Heap::OS2Heap(DWORD flOptions, DWORD dwInitialSize, DWORD dwMaximumSize)
[4]74{
[8877]75 OS2Heap *curheap = OS2Heap::heap;
[7027]76
[7360]77#ifdef DEBUG
[8877]78 totalAlloc = 0;
[7360]79#endif
[8877]80 fInitialized = 0;
81 nrHeaps = 0;
82 heapelem = NULL;
[4]83
[8877]84 /* round the size up to a multiple of 64K */
85 //NOTE: MUST use 64kb here or else we are at risk of running out of virtual
86 // memory space. (when allocating 4kb we actually get 4kb + 60k uncommited)
87 dwInitialSize = ( (dwInitialSize / 65536) + 1) * 65536;
[6366]88
[8877]89 this->dwMaximumSize = dwMaximumSize;
90 this->dwInitialSize = dwInitialSize;
91 this->flOptions = flOptions;
[4]92
[8877]93 heaplistmutex.enter();
94 if(curheap != NULL) {
[4]95 while(curheap->next != NULL) {
96 curheap = curheap->next;
97 }
98 curheap->next = this;
[8877]99 }
100 else heap = this;
101 next = NULL;
[4]102
[21302]103#ifdef RAS
104 if (!rthHeap)
105 {
106 RasRegisterObjectTracking (&rthHeap, "Heap*, Global* and Local* memory",
107 0, RAS_TRACK_FLAG_MEMORY | RAS_TRACK_FLAG_LOG_AT_EXIT,
108 NULL, NULL);
109 }
110#endif
111
[8877]112 heaplistmutex.leave();
[6354]113
[8877]114 APIRET rc;
[6354]115
[8877]116 rc = DosAllocMem((PPVOID)&pInitialHeapMem, dwInitialSize, PAG_READ|PAG_WRITE|PAG_COMMIT);
117 if(rc != 0) {
118 dprintf(("OS2Heap::OS2Heap: DosAllocSharedMem failed with %d", rc));
[6354]119 DebugInt3();
[8877]120 }
121 uheap = _ucreate(pInitialHeapMem, dwInitialSize, _BLOCK_CLEAN,
122 _HEAP_REGULAR, getmoreHeapMem, releaseHeapMem);
123 if(uheap == NULL) {
124 DosFreeMem(pInitialHeapMem);
[6354]125 pInitialHeapMem = NULL;
[8877]126 dprintf(("OS2Heap::OS2Heap: _ucreate failed!"));
[6354]127 DebugInt3();
[8877]128 }
129 hPrimaryHeap = (HANDLE)uheap;
130 dprintf(("KERNEL32: HeapCreate: initial size %d, max size %d (flags %X) returned %X\n", dwInitialSize, dwMaximumSize, flOptions, hPrimaryHeap));
[4]131}
132//******************************************************************************
133//******************************************************************************
134OS2Heap::~OS2Heap()
135{
[8877]136 OS2Heap *curheap = OS2Heap::heap;
137 int i;
[7027]138
[8877]139 // invalidate handle cache
140 fhhm_lastHandle = 0;
141 fhhm_lastHeap = NULL;
[7027]142
[8877]143 dprintf(("dtr OS2Heap, hPrimaryHeap = %X\n", hPrimaryHeap));
[4]144
[8877]145 heaplistmutex.enter();
146 if(heap == this) {
[4]147 heap = next;
[8877]148 }
149 else {
[4]150 while(curheap->next != NULL) {
151 if(curheap->next == this) {
152 curheap->next = next;
153 break;
154 }
155 curheap = curheap->next;
156 }
[8877]157 }
158 heaplistmutex.leave();
[6354]159
[8877]160 if(uheap) {
161 _uclose(uheap);
162 _udestroy(uheap, _FORCE);
163 uheap = NULL;
164 }
165 if(pInitialHeapMem) {
166 DosFreeMem(pInitialHeapMem);
167 pInitialHeapMem = NULL;
168 }
[6354]169
[8877]170 dprintf(("dtr OS2Heap, hPrimaryHeap = %X done\n", hPrimaryHeap));
[4]171}
172//******************************************************************************
173//******************************************************************************
174LPVOID OS2Heap::Alloc(DWORD dwFlags, DWORD dwBytes)
175{
[8877]176 HEAPELEM *lpHeapObj;
177 LPVOID lpMem;
178 DWORD dwAllocBytes;
[4]179
[21932]180#if 0
181 extern HANDLE Heap_ProcessHeap;
182 dprintf(("OS2Heap::Alloc(%x:%x:%x) %x %d\n",
183 this, getHeapHandle(), Heap_ProcessHeap, dwFlags, dwBytes));
184#endif
[7728]185
[8877]186 //size must be multiple of 8 bytes
187 dwAllocBytes = HEAP_ALIGN(dwBytes);
[7728]188
[8877]189 lpMem = _umalloc(uheap, dwAllocBytes + HEAP_OVERHEAD);
190 if(lpMem == NULL) {
191 dprintf(("OS2Heap::Alloc, lpMem == NULL"));
192 return(NULL);
193 }
[21302]194
195 RasTrackMemAlloc (rthHeap, dwAllocBytes);
196
[8877]197 if(dwFlags & HEAP_ZERO_MEMORY) {
198 memset(lpMem, 0, dwAllocBytes+HEAP_OVERHEAD);
199 }
[7360]200
201#ifdef DEBUG
[8877]202 totalAlloc += dwAllocBytes;
[7360]203#endif
204
[8877]205 //align at 8 byte boundary
206 lpHeapObj = (HEAPELEM *)HEAP_ALIGN(lpMem);
207 lpHeapObj->lpMem = lpMem;
208 lpHeapObj->magic = MAGIC_NR_HEAP;
209 lpHeapObj->orgsize = dwBytes; //original size
210 lpHeapObj->cursize = dwBytes; //original size
[7728]211
[8877]212 return(LPVOID)(lpHeapObj+1);
[4]213}
214//******************************************************************************
215//******************************************************************************
[404]216DWORD OS2Heap::Size(DWORD dwFlags, PVOID lpMem)
217{
[8877]218 HEAPELEM *helem = GET_HEAPOBJ(lpMem);
[404]219
[8877]220 if(lpMem == NULL) {
[6080]221 dprintf(("OS2Heap::Size lpMem == NULL\n"));
222 return -1;
[8877]223 }
224 /* verify lpMem address */
225 if (lpMem >= (LPVOID)ulMaxAddr || lpMem < (LPVOID)0x10000)
226 {
227 dprintf(("OS2Heap::Size ERROR BAD HEAP POINTER:%X\n", lpMem));
[6080]228 return -1;
[8877]229 }
[6080]230
[8877]231 if(helem->magic != MAGIC_NR_HEAP)
232 {
[6080]233 dprintf(("OS2Heap::Size ERROR BAD HEAP POINTER:%X\n", lpMem));
234 return -1;
[8877]235 }
236 return helem->cursize; //return current size of memory block
[404]237}
238//******************************************************************************
239//******************************************************************************
[4]240LPVOID OS2Heap::ReAlloc(DWORD dwFlags, LPVOID lpMem, DWORD dwBytes)
241{
[8877]242 HEAPELEM *helem = GET_HEAPOBJ(lpMem);
243 LPVOID lpNewMem;
244 int i, maxSize;
[4]245
[8877]246 if (dwBytes == 0) return NULL; // intercept stupid parameters
[1770]247
[8877]248 //NOTE: Allocate memory using Alloc -> WINE controls depend on this, even
249 // though it apparently doesn't work in Windows.
250 if (lpMem == 0) return Alloc(dwFlags, dwBytes);
[1104]251// if (lpMem == 0) return NULL;
[404]252
[8877]253 if (helem->magic != MAGIC_NR_HEAP)
254 {
255 dprintf(("OS2Heap::ReAlloc ERROR BAD HEAP POINTER:%X\n", lpMem));
256 return lpMem;
257 }
[1118]258
[8877]259 maxSize = HEAP_ALIGN(helem->orgsize);
260 if (dwBytes <= maxSize) {
261 dprintf(("ReAlloc with smaller size than original (%d); return old pointer", maxSize));
[21302]262
263 RasTrackMemRealloc (rthHeap, helem->cursize, dwBytes);
264
[8877]265 //update current size so HeapSize will return the right value
266 helem->cursize = dwBytes;
267 return lpMem; // if reallocation with same size don't do anything
268 }
269 lpNewMem = Alloc(dwFlags, dwBytes);
270 memcpy(lpNewMem, lpMem, dwBytes < maxSize ? dwBytes : maxSize);
271 Free(0, lpMem);
[4]272
[8877]273 if(lpNewMem == NULL)
274 {
275 dprintf(("OS2Heap::ReAlloc, no more memory left\n"));
276 }
277
278 return(lpNewMem);
[4]279}
280//******************************************************************************
281//******************************************************************************
282BOOL OS2Heap::Free(DWORD dwFlags, LPVOID lpMem)
283{
[8877]284 HEAPELEM *helem = GET_HEAPOBJ(lpMem);
[4]285
[8877]286 /* verify lpMem address */
287 if (lpMem >= (LPVOID)ulMaxAddr || lpMem < (LPVOID)0x10000)
288 {
[3464]289 dprintf(("OS2Heap::Free ERROR BAD HEAP POINTER:%X\n", lpMem));
290 return FALSE;
[8877]291 }
[1118]292
[8877]293 if(helem->magic != MAGIC_NR_HEAP)
294 {
[3464]295 dprintf(("OS2Heap::Free ERROR BAD HEAP POINTER:%X\n", lpMem));
296 return FALSE;
[8877]297 }
[1118]298
[4]299#ifdef DEBUG1
[8877]300 int size = Size(0, lpMem);
301 dprintf(("OS2Heap::Free lpMem = %X, size %d\n", lpMem, size));
[7360]302#ifdef DEBUG
[8877]303 totalAlloc -= size;
[4]304#endif
[7360]305#endif
[4]306
[21302]307 RasTrackMemFree (rthHeap, helem->cursize);
308
[8877]309 free(helem->lpMem);
[21302]310
[8877]311 return(TRUE);
[4]312}
313//******************************************************************************
314//******************************************************************************
315DWORD OS2Heap::Compact(DWORD dwFlags)
316{
[8877]317 dprintf(("OS2Heap::Compact, %X- stub\n", dwFlags));
318 return(0);
[4]319}
320//******************************************************************************
321//******************************************************************************
322BOOL OS2Heap::Validate(DWORD dwFlags, LPCVOID lpMem)
323{
[8877]324 HEAPELEM *helem = GET_HEAPOBJ(lpMem);
[6354]325
[8877]326 dprintf(("OS2Heap::Validate, %X %X", dwFlags, lpMem));
[6354]327
[8877]328 /* verify lpMem address */
329 if (lpMem >= (LPVOID)ulMaxAddr || lpMem < (LPVOID)0x10000)
330 {
[6354]331 dprintf(("OS2Heap::Validate BAD HEAP POINTER:%X\n", lpMem));
332 return FALSE;
[8877]333 }
[6354]334
[8877]335 if(helem->magic != MAGIC_NR_HEAP)
336 {
[6354]337 dprintf(("OS2Heap::Validate BAD HEAP POINTER:%X\n", lpMem));
338 return FALSE;
[8877]339 }
340 return(TRUE);
[4]341}
342//******************************************************************************
343//******************************************************************************
344BOOL OS2Heap::Walk(void *lpEntry)
345{
[8877]346 dprintf(("OS2Heap::Walk, %X - stub? (TRUE)\n", lpEntry));
347 return(TRUE);
[4]348}
349//******************************************************************************
350//******************************************************************************
351OS2Heap *OS2Heap::find(HANDLE hHeap)
352{
[7358]353/* PH moved to inlineable macro ...
354 * // check against cache first
355 * if (fhhm_lastHeap)
356 * if (hHeap == fhhm_lastHandle)
357 * {
358 * return fhhm_lastHeap;
359 * }
360 *
361 */
362
[4]363 OS2Heap *curheap = OS2Heap::heap;
[7027]364
[672]365 //@@@PH NT programs seem to assume heap 0 is always valid?!
366 if (hHeap == 0)
[7027]367 if (curheap != NULL)
368 {
369 fhhm_lastHandle = hHeap;
370 fhhm_lastHeap = curheap;
371 return curheap;
372 }
[672]373
[7027]374 while(curheap != NULL)
375 {
376 if(curheap->hPrimaryHeap == hHeap)
377 {
378 fhhm_lastHandle = hHeap;
379 fhhm_lastHeap = curheap;
380 return(curheap);
381 }
382 curheap = curheap->next;
[4]383 }
384 dprintf(("Heap %X not found!\n", hHeap));
[7027]385 fhhm_lastHandle = hHeap;
386 fhhm_lastHeap = NULL;
[4]387 return(NULL);
388}
389//******************************************************************************
390//******************************************************************************
391OS2Heap *OS2Heap::heap = NULL;
[6354]392
[7360]393
[6354]394//******************************************************************************
395//******************************************************************************
396void * _LNK_CONV getmoreHeapMem(Heap_t pHeap, size_t *size, int *clean)
397{
[8877]398 APIRET rc;
399 PVOID newblock;
[6354]400
[8877]401 dprintf(("KERNEL32: getmoreHeapMem(%08xh, %08xh, %08xh)", pHeap, *size, *clean));
[6354]402
[8877]403 /* round the size up to a multiple of 64K */
404 //NOTE: MUST use 64kb here or else we are at risk of running out of virtual
405 // memory space. (when allocating 4kb we actually get 4kb + 60k uncommited)
406 *size = ( (*size / 65536) + 1) * 65536;
[6354]407
[8877]408 rc = DosAllocMem(&newblock, *size, PAG_READ|PAG_WRITE|PAG_COMMIT|PAG_EXECUTE);
409 if(rc != 0) {
410 dprintf(("getmoreHeapMem: DosAllocMem failed with %d", rc));
411 return FALSE;
412 }
413 *clean = _BLOCK_CLEAN;
414 dprintf(("KERNEL32: getmoreHeapMem %x %d", newblock, *size));
415 return newblock;
[6354]416}
417//******************************************************************************
418//******************************************************************************
419void _LNK_CONV releaseHeapMem(Heap_t pHeap, void *block, size_t size)
420{
[8877]421 dprintf(("KERNEL32: releaseHeapMem %x %x %d", pHeap, block, size));
422 DosFreeMem(block);
[6354]423}
424//******************************************************************************
425//******************************************************************************
Note: See TracBrowser for help on using the repository browser.