source: trunk/src/kernel32/heapshared.cpp@ 21916

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

Merge branch gcc-kmk to trunk.

File size: 9.3 KB
Line 
1/* $Id: heapshared.cpp,v 1.11 2003-01-13 16:51:39 sandervl Exp $ */
2/*
3 * Shared heap functions for OS/2
4 *
5 * Initially commit 16 kb, add more when required
6 *
7 * NOTE: Hardcoded limit of 512 KB (increase when required)
8 *
9 * TODO: Not process/thread safe (initializing/destroying heap)
10 *
11 * ASSUMPTION: Rtl library takes care of protection of heap increase/decrease
12 * (from multiple threads/processes)
13 *
14 * Copyright 1999 Sander van Leeuwen (sandervl@xs4all.nl)
15 *
16 */
17#define INCL_BASE
18#define INCL_DOSMEMMGR
19#define INCL_DOSPROCESS
20#include <os2wrap.h>
21#include <string.h>
22#include <dbglog.h>
23#include <stddef.h>
24#include <stdlib.h>
25#include <umalloc.h>
26#include "initterm.h"
27
28#define PAGE_SIZE 4096
29
30#define DBG_LOCALLOG DBG_heapshared
31#include "dbglocal.h"
32
33#define MAX_HEAPSIZE (2048*1024)
34#define MAX_HEAPPAGES (MAX_HEAPSIZE/PAGE_SIZE)
35#define INCR_HEAPSIZE (16*1024)
36
37//
38// Global DLL Data (keep it in sync with globaldata.asm!)
39//
40extern Heap_t sharedHeap; // = 0
41extern PVOID pSharedMem; // = NULL
42extern BYTE pageBitmap[MAX_HEAPPAGES]; // = {0}
43extern ULONG refCount; // = 0;
44
45static int privateRefCount = 0;
46
47void * _LNK_CONV getmoreShared(Heap_t pHeap, size_t *size, int *clean);
48void _LNK_CONV releaseShared(Heap_t pHeap, void *block, size_t size);
49
50//******************************************************************************
51//******************************************************************************
52BOOL SYSTEM InitializeSharedHeap()
53{
54 APIRET rc;
55 ULONG flAllocMem = 0, ulSysinfo;
56
57 //necessary until next WGSS update
58 if(++privateRefCount > 1) {
59 return TRUE;
60 }
61
62 rc = DosQuerySysInfo(QSV_VIRTUALADDRESSLIMIT, QSV_VIRTUALADDRESSLIMIT, &ulSysinfo, sizeof(ulSysinfo));
63 if (rc == 0 && ulSysinfo > 512) //VirtualAddresslimit is in MB
64 {
65 flAllocMem = PAG_ANY;
66 }
67
68 if(pSharedMem == NULL) {
69 rc = DosAllocSharedMem(&pSharedMem, NULL, MAX_HEAPSIZE, PAG_READ|PAG_WRITE|OBJ_GETTABLE|flAllocMem);
70 if(rc != 0) {
71 dprintf(("InitializeSharedHeap: DosAllocSharedMem failed with %d", rc));
72 return FALSE;
73 }
74 rc = DosSetMem(pSharedMem, INCR_HEAPSIZE, PAG_READ|PAG_WRITE|PAG_COMMIT);
75 if(rc != 0) {
76 DosFreeMem(pSharedMem);
77 dprintf(("InitializeSharedHeap: DosSetMem failed with %d", rc));
78 return FALSE;
79 }
80 sharedHeap = _ucreate(pSharedMem, INCR_HEAPSIZE, _BLOCK_CLEAN, _HEAP_REGULAR|_HEAP_SHARED,
81 getmoreShared, releaseShared);
82
83 if(sharedHeap == NULL) {
84 DosFreeMem(pSharedMem);
85 dprintf(("InitializeSharedHeap: _ucreate failed!"));
86 return FALSE;
87 }
88 dprintf(("KERNEL32: First InitializeSharedHeap %x %x", pSharedMem, sharedHeap));
89 for(int i=0;i<INCR_HEAPSIZE/PAGE_SIZE;i++) {
90 pageBitmap[i] = 1; //mark as committed
91 }
92 }
93 else {
94 if(DosGetSharedMem(pSharedMem, PAG_READ|PAG_WRITE) != 0) {
95 dprintf(("InitializeSharedHeap: DosGetSharedMem failed!"));
96 return FALSE;
97 }
98 dprintf(("KERNEL32: InitializeSharedHeap %x %x refcount %d", pSharedMem, sharedHeap, refCount));
99 if(_uopen(sharedHeap) != 0) {
100 dprintf(("InitializeSharedHeap: unable to open shared heap!"));
101 return FALSE;
102 }
103 }
104 refCount++;
105 return TRUE;
106}
107//******************************************************************************
108//******************************************************************************
109#ifdef DEBUG
110int _LNK_CONV callback_function(const void *pentry, size_t sz, int useflag, int status,
111 const char *filename, size_t line)
112{
113 if (_HEAPOK != status) {
114 dprintf(("status is not _HEAPOK."));
115 return 1;
116 }
117 if (_USEDENTRY == useflag && sz && filename && line) {
118 dprintf(("allocated %08x %u at %s %d\n", pentry, sz, filename, line));
119 }
120 else dprintf(("allocated %08x %u", pentry, sz));
121
122 return 0;
123}
124#endif
125//******************************************************************************
126//******************************************************************************
127void SYSTEM DestroySharedHeap()
128{
129 dprintf(("KERNEL32: DestroySharedHeap %d", refCount));
130 if(--privateRefCount > 0) {
131 return;
132 }
133
134#ifdef DEBUG
135 _uheap_walk(sharedHeap, callback_function);
136 dprintf((NULL));
137#endif
138
139 if(--refCount == 0) {
140 if(sharedHeap) {
141 _uclose(sharedHeap);
142 _udestroy(sharedHeap, _FORCE);
143 sharedHeap = NULL;
144 }
145 if(pSharedMem) {
146 DosFreeMem(pSharedMem);
147 pSharedMem = NULL;
148 }
149 }
150 else {
151 _uclose(sharedHeap);
152 }
153}
154//******************************************************************************
155//******************************************************************************
156ULONG GetPageRangeFree(ULONG pageoffset)
157{
158 dprintf(("KERNEL32: GetPageRangeFree(%08xh)", pageoffset));
159
160 int i;
161 for(i=pageoffset;i<MAX_HEAPPAGES;i++) {
162 if(pageBitmap[i] == 1) {
163 break;
164 }
165 }
166 return i-pageoffset;
167}
168//******************************************************************************
169//******************************************************************************
170void * _LNK_CONV getmoreShared(Heap_t pHeap, size_t *size, int *clean)
171{
172 APIRET rc;
173 ULONG newsize;
174 PVOID newblock;
175
176 dprintf(("KERNEL32: getmoreShared(%08xh, %08xh, %08xh)\n", pHeap, *size, *clean));
177
178 /* round the size up to a multiple of 4K */
179 // *size = (*size / 4096) * 4096 + 4096;
180 // @@@PH speed improvement
181 *size = (*size + 4096) & 0xFFFFF000;
182 *size = max(*size, INCR_HEAPSIZE);
183
184 for(int i=0;i<MAX_HEAPPAGES;i++)
185 {
186 int nrpagesfree = GetPageRangeFree(i);
187 if(nrpagesfree >= *size/PAGE_SIZE)
188 {
189 newblock = (PVOID)((ULONG)pSharedMem + i*PAGE_SIZE);
190 rc = DosSetMem(newblock, *size, PAG_READ|PAG_WRITE|PAG_COMMIT);
191 if(rc != 0) {
192 dprintf(("getmoreShared: DosSetMem failed with %d", rc));
193 return NULL;
194 }
195 for(int j=0;j < *size/PAGE_SIZE; j++)
196 {
197 pageBitmap[i+j] = 1; //mark as committed
198 }
199
200 *clean = _BLOCK_CLEAN;
201 dprintf(("KERNEL32: getmoreShared %x %d", newblock, *size));
202 return newblock;
203 }
204 if(nrpagesfree)
205 i += nrpagesfree-1;
206 }
207 dprintf(("KERNEL32: getmoreShared NOTHING LEFT (%d)", *size));
208 return NULL;
209}
210//******************************************************************************
211//******************************************************************************
212void _LNK_CONV releaseShared(Heap_t pHeap, void *block, size_t size)
213{
214 ULONG pagenr;
215
216 dprintf(("KERNEL32: releaseShared %x %d", block, size));
217 DosSetMem(block, size, PAG_READ|PAG_WRITE|PAG_DECOMMIT);
218
219 pagenr = (ULONG)block - (ULONG)pSharedMem;
220 pagenr /= PAGE_SIZE;
221 for(int i=pagenr;i<pagenr+size/PAGE_SIZE;i++) {
222 pageBitmap[i] = 0; //mark as decommitted
223 }
224}
225//******************************************************************************
226//******************************************************************************
227void * SYSTEM _smalloc(int size)
228{
229 void *chunk;
230
231 chunk = _umalloc(sharedHeap, size);
232 dprintf(("_smalloc %x returned %x", size, chunk));
233 return chunk;
234}
235//******************************************************************************
236//******************************************************************************
237void * SYSTEM _smallocfill(int size, int filler)
238{
239 void *chunk;
240
241 chunk = _umalloc(sharedHeap, size);
242 if(chunk) {
243 memset(chunk, 0, size);
244 }
245 dprintf(("_smallocfill %x %x returned %x", size, filler, chunk));
246 return chunk;
247}
248//******************************************************************************
249//******************************************************************************
250void SYSTEM _sfree(void *block)
251{
252 dprintf(("_sfree %x", block));
253 free(block);
254}
255//******************************************************************************
256//******************************************************************************
257void * _System _debug_smalloc(int size, const char *pszFile, int linenr)
258{
259 void *chunk;
260
261#ifdef __DEBUG_ALLOC__
262 chunk = _debug_umalloc(sharedHeap, size, pszFile, linenr);
263#else
264 chunk = _umalloc(sharedHeap, size);
265#endif
266 dprintf(("_smalloc %x returned %x", size, chunk));
267 return chunk;
268}
269//******************************************************************************
270//******************************************************************************
271void * _System _debug_smallocfill(int size, int filler, const char *pszFile, int linenr)
272{
273 void *chunk;
274
275#ifdef __DEBUG_ALLOC__
276 chunk = _debug_umalloc(sharedHeap, size, pszFile, linenr);
277#else
278 chunk = _umalloc(sharedHeap, size);
279#endif
280 if(chunk) {
281 memset(chunk, 0, size);
282 }
283 dprintf(("_smallocfill %x %x returned %x", size, filler, chunk));
284 return chunk;
285}
286//******************************************************************************
287//******************************************************************************
288void _System _debug_sfree(void *chunk, const char *pszFile, int linenr)
289{
290 dprintf(("_sfree %x", chunk));
291#ifdef __DEBUG_ALLOC__
292 _debug_free(chunk, pszFile, linenr);
293#else
294 free(chunk);
295#endif
296}
297//******************************************************************************
298//******************************************************************************
Note: See TracBrowser for help on using the repository browser.