source: trunk/src/kernel32/os2heap.cpp@ 6354

Last change on this file since 6354 was 6354, checked in by sandervl, 24 years ago

heap changes/fixes

File size: 10.7 KB
Line 
1/* $Id: os2heap.cpp,v 1.20 2001-07-17 12:10:21 sandervl Exp $ */
2
3/*
4 * Heap class for OS/2
5 *
6 * Copyright 1998 Sander van Leeuwen
7 *
8 *
9 * NOTE: ReAlloc allocates memory using Alloc if memory pointer == NULL
10 * WINE controls depend on this, even though it apparently
11 * doesn't work like this in Windows.
12 *
13 * Project Odin Software License can be found in LICENSE.TXT
14 *
15 */
16#define INCL_DOSMEMMGR
17#define INCL_DOSSEMAPHORES
18#define INCL_DOSERRORS
19#include <os2wrap.h> //Odin32 OS/2 api wrappers
20#include <stdlib.h>
21#include <string.h>
22#include <umalloc.h>
23
24#include "win32type.h"
25#include "os2heap.h"
26#include "misc.h"
27#include "vmutex.h"
28#include "initterm.h"
29#include <odin32validate.h>
30
31#define DBG_LOCALLOG DBG_os2heap
32#include "dbglocal.h"
33
34#ifndef HEAP_NO_SERIALIZE
35 #define HEAP_NO_SERIALIZE 1
36#endif
37
38#ifndef HEAP_ZERO_MEMORY
39 #define HEAP_ZERO_MEMORY 8
40#endif
41
42VMutex heaplistmutex; //protects linked lists of heaps
43
44void * _LNK_CONV getmoreHeapMem(Heap_t pHeap, size_t *size, int *clean);
45void _LNK_CONV releaseHeapMem(Heap_t pHeap, void *block, size_t size);
46
47//******************************************************************************
48//******************************************************************************
49OS2Heap::OS2Heap(HANDLE hHeap, DWORD flOptions, DWORD dwInitialSize, DWORD dwMaximumSize)
50{
51 OS2Heap *curheap = OS2Heap::heap;
52
53 hPrimaryHeap = hHeap;
54 totalAlloc = 0;
55 fInitialized = 0;
56 nrHeaps = 0;
57 heapelem = NULL;
58
59 this->dwMaximumSize = dwMaximumSize;
60 this->dwInitialSize = (dwInitialSize) ? dwInitialSize : 0x4000;
61 this->flOptions = flOptions;
62
63 dprintf(("KERNEL32: HeapCreate: initial size %d, max size %d (flags %X) returned %X\n", dwInitialSize, dwMaximumSize, flOptions, hPrimaryHeap));
64
65 if(!(flOptions & HEAP_NO_SERIALIZE))
66 {
67 hmutex = new VMutex();
68 dassert(hmutex, ("ERROR: new VMutex\n"));
69 }
70 else hmutex = NULL;
71
72 heaplistmutex.enter();
73 if(curheap != NULL) {
74 while(curheap->next != NULL) {
75 curheap = curheap->next;
76 }
77 curheap->next = this;
78 }
79 else heap = this;
80 next = NULL;
81
82 heaplistmutex.leave();
83
84 APIRET rc;
85
86 rc = DosAllocMem((PPVOID)&pInitialHeapMem, dwInitialSize, PAG_READ|PAG_WRITE|PAG_COMMIT);
87 if(rc != 0) {
88 dprintf(("OS2Heap::OS2Heap: DosAllocSharedMem failed with %d", rc));
89 DebugInt3();
90 }
91 uheap = _ucreate(pInitialHeapMem, dwInitialSize, _BLOCK_CLEAN,
92 _HEAP_REGULAR, getmoreHeapMem, releaseHeapMem);
93 if(uheap == NULL) {
94 DosFreeMem(pInitialHeapMem);
95 pInitialHeapMem = NULL;
96 dprintf(("OS2Heap::OS2Heap: _ucreate failed!"));
97 DebugInt3();
98 }
99}
100//******************************************************************************
101//******************************************************************************
102OS2Heap::~OS2Heap()
103{
104 OS2Heap *curheap = OS2Heap::heap;
105 HEAPELEM *hnext;
106 int i;
107
108 dprintf(("dtr OS2Heap, hPrimaryHeap = %X\n", hPrimaryHeap));
109
110 if(hmutex)
111 hmutex->enter();
112
113 while(heapelem) {
114 hnext = heapelem->next;
115 free(heapelem->lpMem);
116 heapelem = hnext;
117 }
118 if(hmutex)
119 {
120 hmutex->leave();
121 delete(hmutex);
122 }
123
124 heaplistmutex.enter();
125 if(heap == this) {
126 heap = next;
127 }
128 else {
129 while(curheap->next != NULL) {
130 if(curheap->next == this) {
131 curheap->next = next;
132 break;
133 }
134 curheap = curheap->next;
135 }
136 }
137 heaplistmutex.leave();
138
139 if(uheap) {
140 _uclose(uheap);
141 _udestroy(uheap, _FORCE);
142 uheap = NULL;
143 }
144 if(pInitialHeapMem) {
145 DosFreeMem(pInitialHeapMem);
146 pInitialHeapMem = NULL;
147 }
148
149 dprintf(("dtr OS2Heap, hPrimaryHeap = %X done\n", hPrimaryHeap));
150}
151//******************************************************************************
152//******************************************************************************
153LPVOID OS2Heap::Alloc(DWORD dwFlags, DWORD dwBytes)
154{
155 HEAPELEM *lpHeapObj;
156 LPVOID lpMem;
157
158// dprintf(("OS2Heap::Alloc\n"));
159 lpMem = _umalloc(uheap, dwBytes + HEAP_OVERHEAD);
160 if(lpMem == NULL) {
161 dprintf(("OS2Heap::Alloc, lpMem == NULL"));
162 return(NULL);
163 }
164 if(dwFlags & HEAP_ZERO_MEMORY) {
165 memset(lpMem, 0, dwBytes+HEAP_OVERHEAD);
166 }
167 totalAlloc += dwBytes;
168
169 //align at 8 byte boundary
170 lpHeapObj = (HEAPELEM *)(((ULONG)lpMem+7) & ~7);
171 lpHeapObj->lpMem = lpMem;
172
173 if(hmutex)
174 hmutex->enter();
175
176 lpHeapObj->next = heapelem;
177 lpHeapObj->prev = NULL;
178 lpHeapObj->magic = MAGIC_NR_HEAP;
179 if(heapelem) {
180 heapelem->prev = lpHeapObj;
181 }
182 heapelem = lpHeapObj;
183
184 if(hmutex) {
185 hmutex->leave();
186 }
187 return(LPVOID)(lpHeapObj+1);
188}
189//******************************************************************************
190//******************************************************************************
191DWORD OS2Heap::Size(DWORD dwFlags, PVOID lpMem)
192{
193 HEAPELEM *helem = GET_HEAPOBJ(lpMem);
194
195 if(lpMem == NULL) {
196 dprintf(("OS2Heap::Size lpMem == NULL\n"));
197 return -1;
198 }
199 /* verify lpMem address */
200 if (lpMem >= (LPVOID)ulMaxAddr || lpMem < (LPVOID)0x10000)
201 {
202 dprintf(("OS2Heap::Size ERROR BAD HEAP POINTER:%X\n", lpMem));
203 return -1;
204 }
205
206 if(helem->magic != MAGIC_NR_HEAP)
207 {
208 dprintf(("OS2Heap::Size ERROR BAD HEAP POINTER:%X\n", lpMem));
209 return -1;
210 }
211
212 return(_msize(helem->lpMem) - HEAP_OVERHEAD);
213}
214//******************************************************************************
215//******************************************************************************
216LPVOID OS2Heap::ReAlloc(DWORD dwFlags, LPVOID lpMem, DWORD dwBytes)
217{
218 HEAPELEM *helem = GET_HEAPOBJ(lpMem);
219 LPVOID lpNewMem;
220 int i, oldSize;
221
222 if (dwBytes == 0) return NULL; // intercept stupid parameters
223
224 //NOTE: Allocate memory using Alloc -> WINE controls depend on this, even
225 // though it apparently doesn't work in Windows.
226 if (lpMem == 0) return Alloc(dwFlags, dwBytes);
227// if (lpMem == 0) return NULL;
228
229 if (helem->magic != MAGIC_NR_HEAP)
230 {
231 dprintf(("OS2Heap::ReAlloc ERROR BAD HEAP POINTER:%X\n", lpMem));
232 return lpMem;
233 }
234
235 oldSize = Size(0,lpMem);
236 if (oldSize >= dwBytes) {
237 dprintf(("ReAlloc with smaller size than original (%d); return old pointer", oldSize));
238 return lpMem; // if reallocation with same size don't do anything
239 }
240 lpNewMem = Alloc(dwFlags, dwBytes);
241 memcpy(lpNewMem, lpMem, dwBytes < oldSize ? dwBytes : oldSize);
242 Free(0, lpMem);
243
244 if(lpNewMem == NULL)
245 {
246 dprintf(("OS2Heap::ReAlloc, no more memory left\n"));
247 }
248
249 return(lpNewMem);
250}
251//******************************************************************************
252//******************************************************************************
253BOOL OS2Heap::Free(DWORD dwFlags, LPVOID lpMem)
254{
255 HEAPELEM *helem = GET_HEAPOBJ(lpMem);
256
257 if(lpMem == NULL) {
258 dprintf(("OS2Heap::Free lpMem == NULL\n"));
259 return(FALSE);
260 }
261 /* verify lpMem address */
262 if (lpMem >= (LPVOID)ulMaxAddr || lpMem < (LPVOID)0x10000)
263 {
264 dprintf(("OS2Heap::Free ERROR BAD HEAP POINTER:%X\n", lpMem));
265 return FALSE;
266 }
267
268 if(helem->magic != MAGIC_NR_HEAP)
269 {
270 dprintf(("OS2Heap::Free ERROR BAD HEAP POINTER:%X\n", lpMem));
271 return FALSE;
272 }
273
274#ifdef DEBUG1
275 int size = Size(0, lpMem);
276 dprintf(("OS2Heap::Free lpMem = %X, size %d\n", lpMem, size));
277 totalAlloc -= size;
278#endif
279 if(hmutex)
280 hmutex->enter();
281
282 if(helem->prev)
283 helem->prev->next = helem->next;
284 if(helem->next)
285 helem->next->prev = helem->prev;
286 if(heapelem == helem)
287 heapelem = heapelem->next;
288
289 if(hmutex) {
290 hmutex->leave();
291 }
292
293 free(helem->lpMem);
294 return(TRUE);
295}
296//******************************************************************************
297//******************************************************************************
298DWORD OS2Heap::Compact(DWORD dwFlags)
299{
300 dprintf(("OS2Heap::Compact, %X- stub\n", dwFlags));
301 return(0);
302}
303//******************************************************************************
304//******************************************************************************
305BOOL OS2Heap::Validate(DWORD dwFlags, LPCVOID lpMem)
306{
307 HEAPELEM *helem = GET_HEAPOBJ(lpMem);
308
309 dprintf(("OS2Heap::Validate, %X %X", dwFlags, lpMem));
310
311 if(lpMem == NULL) {
312 dprintf(("OS2Heap::Validate lpMem == NULL\n"));
313 return(FALSE);
314 }
315 /* verify lpMem address */
316 if (lpMem >= (LPVOID)ulMaxAddr || lpMem < (LPVOID)0x10000)
317 {
318 dprintf(("OS2Heap::Validate BAD HEAP POINTER:%X\n", lpMem));
319 return FALSE;
320 }
321
322 if(helem->magic != MAGIC_NR_HEAP)
323 {
324 dprintf(("OS2Heap::Validate BAD HEAP POINTER:%X\n", lpMem));
325 return FALSE;
326 }
327 return(TRUE);
328}
329//******************************************************************************
330//******************************************************************************
331BOOL OS2Heap::Walk(void *lpEntry)
332{
333 dprintf(("OS2Heap::Walk, %X - stub? (TRUE)\n", lpEntry));
334 return(TRUE);
335}
336//******************************************************************************
337//******************************************************************************
338OS2Heap *OS2Heap::find(HANDLE hHeap)
339{
340 OS2Heap *curheap = OS2Heap::heap;
341
342 //@@@PH NT programs seem to assume heap 0 is always valid?!
343 if (hHeap == 0)
344 if (curheap != NULL)
345 return curheap;
346
347 while(curheap != NULL) {
348 if(curheap->hPrimaryHeap == hHeap) {
349 return(curheap);
350 }
351 curheap = curheap->next;
352 }
353 dprintf(("Heap %X not found!\n", hHeap));
354 return(NULL);
355}
356//******************************************************************************
357//******************************************************************************
358OS2Heap *OS2Heap::heap = NULL;
359
360//******************************************************************************
361//******************************************************************************
362void * _LNK_CONV getmoreHeapMem(Heap_t pHeap, size_t *size, int *clean)
363{
364 APIRET rc;
365 PVOID newblock;
366
367 dprintf(("KERNEL32: getmoreHeapMem(%08xh, %08xh, %08xh)", pHeap, *size, *clean));
368
369 /* round the size up to a multiple of 4K */
370 *size = (*size / 4096) * 4096 + 4096;
371
372 rc = DosAllocMem(&newblock, *size, PAG_READ|PAG_WRITE|PAG_COMMIT|PAG_EXECUTE);
373 if(rc != 0) {
374 dprintf(("getmoreHeapMem: DosAllocMem failed with %d", rc));
375 return FALSE;
376 }
377 *clean = _BLOCK_CLEAN;
378 dprintf(("KERNEL32: getmoreHeapMem %x %d", newblock, *size));
379 return newblock;
380}
381//******************************************************************************
382//******************************************************************************
383void _LNK_CONV releaseHeapMem(Heap_t pHeap, void *block, size_t size)
384{
385 dprintf(("KERNEL32: releaseHeapMem %x %x %d", pHeap, block, size));
386 DosFreeMem(block);
387}
388//******************************************************************************
389//******************************************************************************
Note: See TracBrowser for help on using the repository browser.