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

Last change on this file since 21388 was 21302, checked in by ydario, 16 years ago

Kernel32 updates.

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//Global DLL Data
38#pragma data_seg(_GLOBALDATA)
39 Heap_t sharedHeap = 0;
40static PVOID pSharedMem = NULL;
41static BYTE pageBitmap[MAX_HEAPPAGES] = {0};
42static ULONG refCount = 0;
43#pragma data_seg()
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 for(int i=pageoffset;i<MAX_HEAPPAGES;i++) {
161 if(pageBitmap[i] == 1) {
162 break;
163 }
164 }
165 return i-pageoffset;
166}
167//******************************************************************************
168//******************************************************************************
169void * _LNK_CONV getmoreShared(Heap_t pHeap, size_t *size, int *clean)
170{
171 APIRET rc;
172 ULONG newsize;
173 PVOID newblock;
174
175 dprintf(("KERNEL32: getmoreShared(%08xh, %08xh, %08xh)\n", pHeap, *size, *clean));
176
177 /* round the size up to a multiple of 4K */
178 // *size = (*size / 4096) * 4096 + 4096;
179 // @@@PH speed improvement
180 *size = (*size + 4096) & 0xFFFFF000;
181 *size = max(*size, INCR_HEAPSIZE);
182
183 for(int i=0;i<MAX_HEAPPAGES;i++)
184 {
185 int nrpagesfree = GetPageRangeFree(i);
186 if(nrpagesfree >= *size/PAGE_SIZE)
187 {
188 newblock = (PVOID)((ULONG)pSharedMem + i*PAGE_SIZE);
189 rc = DosSetMem(newblock, *size, PAG_READ|PAG_WRITE|PAG_COMMIT);
190 if(rc != 0) {
191 dprintf(("getmoreShared: DosSetMem failed with %d", rc));
192 return NULL;
193 }
194 for(int j=0;j < *size/PAGE_SIZE; j++)
195 {
196 pageBitmap[i+j] = 1; //mark as committed
197 }
198
199 *clean = _BLOCK_CLEAN;
200 dprintf(("KERNEL32: getmoreShared %x %d", newblock, *size));
201 return newblock;
202 }
203 if(nrpagesfree)
204 i += nrpagesfree-1;
205 }
206 dprintf(("KERNEL32: getmoreShared NOTHING LEFT (%d)", *size));
207 return NULL;
208}
209//******************************************************************************
210//******************************************************************************
211void _LNK_CONV releaseShared(Heap_t pHeap, void *block, size_t size)
212{
213 ULONG pagenr;
214
215 dprintf(("KERNEL32: releaseShared %x %d", block, size));
216 DosSetMem(block, size, PAG_READ|PAG_WRITE|PAG_DECOMMIT);
217
218 pagenr = (ULONG)block - (ULONG)pSharedMem;
219 pagenr /= PAGE_SIZE;
220 for(int i=pagenr;i<pagenr+size/PAGE_SIZE;i++) {
221 pageBitmap[i] = 0; //mark as decommitted
222 }
223}
224//******************************************************************************
225//******************************************************************************
226void * SYSTEM _smalloc(int size)
227{
228 void *chunk;
229
230 chunk = _umalloc(sharedHeap, size);
231 dprintf(("_smalloc %x returned %x", size, chunk));
232 return chunk;
233}
234//******************************************************************************
235//******************************************************************************
236void * SYSTEM _smallocfill(int size, int filler)
237{
238 void *chunk;
239
240 chunk = _umalloc(sharedHeap, size);
241 if(chunk) {
242 memset(chunk, 0, size);
243 }
244 dprintf(("_smallocfill %x %x returned %x", size, filler, chunk));
245 return chunk;
246}
247//******************************************************************************
248//******************************************************************************
249void SYSTEM _sfree(void *block)
250{
251 dprintf(("_sfree %x", block));
252 free(block);
253}
254//******************************************************************************
255//******************************************************************************
256void * _System _debug_smalloc(int size, char *pszFile, int linenr)
257{
258 void *chunk;
259
260#ifdef __DEBUG_ALLOC__
261 chunk = _debug_umalloc(sharedHeap, size, pszFile, linenr);
262#else
263 chunk = _umalloc(sharedHeap, size);
264#endif
265 dprintf(("_smalloc %x returned %x", size, chunk));
266 return chunk;
267}
268//******************************************************************************
269//******************************************************************************
270void * _System _debug_smallocfill(int size, int filler, char *pszFile, int linenr)
271{
272 void *chunk;
273
274#ifdef __DEBUG_ALLOC__
275 chunk = _debug_umalloc(sharedHeap, size, pszFile, linenr);
276#else
277 chunk = _umalloc(sharedHeap, size);
278#endif
279 if(chunk) {
280 memset(chunk, 0, size);
281 }
282 dprintf(("_smallocfill %x %x returned %x", size, filler, chunk));
283 return chunk;
284}
285//******************************************************************************
286//******************************************************************************
287void _System _debug_sfree(void *chunk, char *pszFile, int linenr)
288{
289 dprintf(("_sfree %x", chunk));
290#ifdef __DEBUG_ALLOC__
291 _debug_free(chunk, pszFile, linenr);
292#else
293 free(chunk);
294#endif
295}
296//******************************************************************************
297//******************************************************************************
Note: See TracBrowser for help on using the repository browser.