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

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

allocate in 64kb units

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