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

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

removed builtin.h include + initterm update

File size: 10.9 KB
Line 
1/* $Id: os2heap.cpp,v 1.16 2001-03-13 18:45:33 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
23#include "win32type.h"
24#include "os2heap.h"
25#include "misc.h"
26#include "vmutex.h"
27#include "initterm.h"
28#include <odin32validate.h>
29
30#define DBG_LOCALLOG DBG_os2heap
31#include "dbglocal.h"
32
33#ifndef HEAP_NO_SERIALIZE
34 #define HEAP_NO_SERIALIZE 1
35#endif
36
37#ifndef HEAP_ZERO_MEMORY
38 #define HEAP_ZERO_MEMORY 8
39#endif
40
41VMutex heaplistmutex; //protects linked lists of heaps
42
43//******************************************************************************
44//******************************************************************************
45OS2Heap::OS2Heap(HANDLE hHeap, DWORD flOptions, DWORD dwInitialSize, DWORD dwMaximumSize)
46{
47 OS2Heap *curheap = OS2Heap::heap;
48
49 hPrimaryHeap = hHeap;
50 totalAlloc = 0;
51 fInitialized = 0;
52 nrHeaps = 0;
53 heapelem = NULL;
54
55 this->dwMaximumSize = dwMaximumSize;
56 this->dwInitialSize = dwInitialSize;
57 this->flOptions = flOptions;
58
59 dprintf(("KERNEL32: HeapCreate: initial size %d, max size %d (flags %X) returned %X\n", dwInitialSize, dwMaximumSize, flOptions, hPrimaryHeap));
60
61 if(!(flOptions & HEAP_NO_SERIALIZE))
62 {
63 hmutex = new VMutex();
64 dassert(hmutex, ("ERROR: new VMutex\n"));
65 }
66 else hmutex = NULL;
67
68 heaplistmutex.enter();
69 if(curheap != NULL) {
70 while(curheap->next != NULL) {
71 curheap = curheap->next;
72 }
73 curheap->next = this;
74 }
75 else heap = this;
76 next = NULL;
77
78 heaplistmutex.leave();
79}
80//******************************************************************************
81//******************************************************************************
82OS2Heap::~OS2Heap()
83{
84 OS2Heap *curheap = OS2Heap::heap;
85 HEAPELEM *hnext;
86 int i;
87
88 dprintf(("dtr OS2Heap, hPrimaryHeap = %X\n", hPrimaryHeap));
89
90 if(hmutex)
91 hmutex->enter();
92
93 while(heapelem) {
94 hnext = heapelem->next;
95 free(heapelem);
96 heapelem = hnext;
97 }
98 if(hmutex)
99 {
100 hmutex->leave();
101 delete(hmutex);
102 }
103
104 heaplistmutex.enter();
105 if(heap == this) {
106 heap = next;
107 }
108 else {
109 while(curheap->next != NULL) {
110 if(curheap->next == this) {
111 curheap->next = next;
112 break;
113 }
114 curheap = curheap->next;
115 }
116 }
117 heaplistmutex.leave();
118 dprintf(("dtr OS2Heap, hPrimaryHeap = %X done\n", hPrimaryHeap));
119}
120//******************************************************************************
121//******************************************************************************
122LPVOID OS2Heap::Alloc(DWORD dwFlags, DWORD dwBytes)
123{
124 LPVOID lpMem;
125
126// dprintf(("OS2Heap::Alloc\n"));
127 lpMem = malloc(dwBytes + HEAP_OVERHEAD);
128 if(lpMem == NULL) {
129 dprintf(("OS2Heap::Alloc, lpMem == NULL"));
130 return(NULL);
131 }
132 if(dwFlags & HEAP_ZERO_MEMORY) {
133 memset((char *)lpMem, 0, dwBytes+HEAP_OVERHEAD);
134 }
135 totalAlloc += dwBytes;
136
137 if(hmutex)
138 hmutex->enter();
139
140 if(heapelem) {
141 HEAPELEM *hnext;
142
143 hnext = heapelem;
144
145 heapelem = (HEAPELEM *)lpMem;
146 hnext->prev = heapelem;
147 heapelem->next = hnext;
148 }
149 else {
150 heapelem = (HEAPELEM *)lpMem;
151 heapelem->next = NULL;
152 }
153 heapelem->prev = NULL;
154 heapelem->flags = 0; //only used when allocated with LocalAlloc
155 heapelem->lockCnt = 0; //.. ..
156 heapelem->magic = MAGIC_NR_HEAP;
157
158 if(hmutex) {
159 hmutex->leave();
160 }
161 return(LPVOID)((char *)lpMem+sizeof(HEAPELEM));
162}
163//******************************************************************************
164//******************************************************************************
165LPVOID OS2Heap::Alloc(DWORD dwFlags, DWORD dwBytes, DWORD LocalAllocFlags)
166{
167 HEAPELEM *helem;
168 LPVOID lpMem = Alloc(dwFlags, dwBytes);
169
170 if(lpMem == NULL)
171 return(NULL);
172
173 helem = (HEAPELEM *)((char *)lpMem - sizeof(HEAPELEM));
174 helem->flags = LocalAllocFlags;
175 return(lpMem);
176}
177//******************************************************************************
178//******************************************************************************
179BOOL OS2Heap::Lock(LPVOID lpMem)
180{
181 HEAPELEM *helem = (HEAPELEM *)((char *)lpMem - sizeof(HEAPELEM));
182
183 if((ULONG)lpMem > ADDRESS_SPACE_LIMIT) {
184 //SvL: Some apps lock and unlock gdi handles; just ignore this here
185 dprintf(("Lock: invalid address %x", lpMem));
186 return FALSE;
187 }
188
189 if(lpMem == NULL)
190 return(FALSE);
191
192 if(helem->magic != MAGIC_NR_HEAP)
193 {
194 dprintf(("OS2Heap::Lock ERROR BAD HEAP POINTER:%X\n", lpMem));
195 return FALSE;
196 }
197
198 helem->lockCnt++;
199
200 return(TRUE);
201}
202//******************************************************************************
203//******************************************************************************
204BOOL OS2Heap::Unlock(LPVOID lpMem)
205{
206 HEAPELEM *helem = (HEAPELEM *)((char *)lpMem - sizeof(HEAPELEM));
207
208 if((ULONG)lpMem > ADDRESS_SPACE_LIMIT) {
209 //SvL: Some apps lock and unlock gdi handles; just ignore this here
210 dprintf(("Unlock: invalid address %x", lpMem));
211 return FALSE;
212 }
213
214 if(lpMem == NULL)
215 return(FALSE);
216
217 if(helem->lockCnt == 0)
218 return(FALSE);
219
220 if(helem->magic != MAGIC_NR_HEAP)
221 {
222 dprintf(("OS2Heap::UnLock ERROR BAD HEAP POINTER:%X\n", lpMem));
223 return FALSE;
224 }
225
226 helem->lockCnt--;
227
228 return(TRUE);
229}
230//******************************************************************************
231//******************************************************************************
232DWORD OS2Heap::GetFlags(LPVOID lpMem)
233{
234 HEAPELEM *helem = (HEAPELEM *)((char *)lpMem - sizeof(HEAPELEM));
235
236 if(lpMem == NULL)
237 return(0);
238
239 if(helem->magic != MAGIC_NR_HEAP)
240 {
241 dprintf(("OS2Heap::GetFlags ERROR BAD HEAP POINTER:%X\n", lpMem));
242 return 0;
243 }
244
245 return(helem->lockCnt | (helem->flags << 8));
246}
247//******************************************************************************
248//******************************************************************************
249int OS2Heap::GetLockCnt(LPVOID lpMem)
250{
251 HEAPELEM *helem = (HEAPELEM *)((char *)lpMem - sizeof(HEAPELEM));
252
253 if((ULONG)lpMem > ADDRESS_SPACE_LIMIT) {
254 //SvL: Some apps lock and unlock gdi handles; just ignore this here
255 dprintf(("GetLockCnt: invalid address %x", lpMem));
256 return FALSE;
257 }
258
259 if(lpMem == NULL)
260 return(0);
261
262 if(helem->magic != MAGIC_NR_HEAP)
263 {
264 dprintf(("OS2Heap::GetLockCnt ERROR BAD HEAP POINTER:%X\n", lpMem));
265 return 0;
266 }
267
268 return(helem->lockCnt);
269}
270//******************************************************************************
271//******************************************************************************
272DWORD OS2Heap::Size(DWORD dwFlags, PVOID lpMem)
273{
274// dprintf(("OS2Heap::Size, %X\n", lpMem));
275 if(lpMem == NULL)
276 return(0);
277
278 return(_msize((char *)lpMem - sizeof(HEAPELEM)) - HEAP_OVERHEAD);
279}
280//******************************************************************************
281//******************************************************************************
282LPVOID OS2Heap::ReAlloc(DWORD dwFlags, LPVOID lpMem, DWORD dwBytes)
283{
284 HEAPELEM *helem = (HEAPELEM *)((char *)lpMem - sizeof(HEAPELEM));
285 LPVOID lpNewMem;
286 int i, oldSize;
287
288 if (dwBytes == 0) return NULL; // intercept stupid parameters
289
290 //NOTE: Allocate memory using Alloc -> WINE controls depend on this, even
291 // though it apparently doesn't work in Windows.
292 if (lpMem == 0) return Alloc(dwFlags, dwBytes);
293// if (lpMem == 0) return NULL;
294
295 if (helem->magic != MAGIC_NR_HEAP)
296 {
297 dprintf(("OS2Heap::ReAlloc ERROR BAD HEAP POINTER:%X\n", lpMem));
298 return lpMem;
299 }
300
301 oldSize = Size(0,lpMem);
302 if (oldSize == dwBytes) return lpMem; // if reallocation with same size
303 // don't do anything
304 lpNewMem = Alloc(dwFlags, dwBytes);
305 memcpy(lpNewMem, lpMem, dwBytes < oldSize ? dwBytes : oldSize);
306 Free(0, lpMem);
307
308 if(lpNewMem == NULL)
309 {
310 dprintf(("OS2Heap::ReAlloc, no more memory left\n"));
311 }
312
313 return(lpNewMem);
314}
315//******************************************************************************
316//******************************************************************************
317BOOL OS2Heap::Free(DWORD dwFlags, LPVOID lpMem)
318{
319 HEAPELEM *helem = (HEAPELEM *)((char *)lpMem - sizeof(HEAPELEM));
320
321 if(lpMem == NULL) {
322 dprintf(("OS2Heap::Free lpMem == NULL\n"));
323 return(FALSE);
324 }
325 /* verify lpMem address */
326 if (lpMem >= (LPVOID)ulMaxAddr || lpMem < (LPVOID)0x10000)
327 {
328 dprintf(("OS2Heap::Free ERROR BAD HEAP POINTER:%X\n", lpMem));
329 return FALSE;
330 }
331
332 if(helem->magic != MAGIC_NR_HEAP)
333 {
334 dprintf(("OS2Heap::Free ERROR BAD HEAP POINTER:%X\n", lpMem));
335 return FALSE;
336 }
337
338#ifdef DEBUG1
339 int size = Size(0, lpMem);
340 dprintf(("OS2Heap::Free lpMem = %X, size %d\n", lpMem, size));
341 totalAlloc -= size;
342#endif
343 if(hmutex)
344 hmutex->enter();
345
346 if(helem->prev)
347 helem->prev->next = helem->next;
348 if(helem->next)
349 helem->next->prev = helem->prev;
350 if(heapelem == helem)
351 heapelem = heapelem->next;
352
353 if(hmutex) {
354 hmutex->leave();
355 }
356
357 free((void *)helem);
358 return(TRUE);
359}
360//******************************************************************************
361//******************************************************************************
362DWORD OS2Heap::Compact(DWORD dwFlags)
363{
364 dprintf(("OS2Heap::Compact, %X- stub\n", dwFlags));
365 return(0);
366}
367//******************************************************************************
368//******************************************************************************
369BOOL OS2Heap::Validate(DWORD dwFlags, LPCVOID lpMem)
370{
371 dprintf(("OS2Heap::Validate, %X %X - stub? (TRUE)\n", dwFlags, lpMem));
372 return(TRUE);
373}
374//******************************************************************************
375//******************************************************************************
376BOOL OS2Heap::Walk(void *lpEntry)
377{
378 dprintf(("OS2Heap::Walk, %X - stub? (TRUE)\n", lpEntry));
379 return(TRUE);
380}
381//******************************************************************************
382//******************************************************************************
383OS2Heap *OS2Heap::find(HANDLE hHeap)
384{
385 OS2Heap *curheap = OS2Heap::heap;
386
387 //@@@PH NT programs seem to assume heap 0 is always valid?!
388 if (hHeap == 0)
389 if (curheap != NULL)
390 return curheap;
391
392 while(curheap != NULL) {
393 if(curheap->hPrimaryHeap == hHeap) {
394 return(curheap);
395 }
396 curheap = curheap->next;
397 }
398 dprintf(("Heap %X not found!\n", hHeap));
399 return(NULL);
400}
401//******************************************************************************
402//******************************************************************************
403OS2Heap *OS2Heap::heap = NULL;
Note: See TracBrowser for help on using the repository browser.