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

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

custom build fixes

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