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

Last change on this file since 5120 was 5075, checked in by sandervl, 25 years ago

heap (shared+code) changes + lx dll unload workaround

File size: 5.4 KB
Line 
1/* $Id: heapshared.cpp,v 1.7 2001-02-09 18:31:05 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#include <os2wrap.h>
20#include <misc.h>
21#include <heapshared.h>
22
23#define DBG_LOCALLOG DBG_heapshared
24#include "dbglocal.h"
25
26//Global DLL Data
27#pragma data_seg(_GLOBALDATA)
28 Heap_t sharedHeap = 0;
29static PVOID pSharedMem = NULL;
30static BYTE pageBitmap[MAX_HEAPPAGES] = {0};
31static ULONG refCount = 0;
32#pragma data_seg()
33
34void * _LNK_CONV getmoreShared(Heap_t pHeap, size_t *size, int *clean);
35void _LNK_CONV releaseShared(Heap_t pHeap, void *block, size_t size);
36
37//******************************************************************************
38//******************************************************************************
39BOOL InitializeSharedHeap()
40{
41 APIRET rc;
42
43 if(pSharedMem == NULL) {
44 dprintf(("KERNEL32: InitializeSharedHeap %x", &sharedHeap));
45 rc = DosAllocSharedMem(&pSharedMem, NULL, MAX_HEAPSIZE, PAG_READ|PAG_WRITE|OBJ_GETTABLE);
46 if(rc != 0) {
47 dprintf(("InitializeSharedHeap: DosAllocSharedMem failed with %d", rc));
48 return FALSE;
49 }
50 rc = DosSetMem(pSharedMem, INCR_HEAPSIZE, PAG_READ|PAG_WRITE|PAG_COMMIT);
51 if(rc != 0) {
52 DosFreeMem(pSharedMem);
53 dprintf(("InitializeSharedHeap: DosSetMem failed with %d", rc));
54 return FALSE;
55 }
56 sharedHeap = _ucreate(pSharedMem, INCR_HEAPSIZE, _BLOCK_CLEAN,
57 _HEAP_REGULAR|_HEAP_SHARED,
58 getmoreShared, releaseShared);
59
60 if(sharedHeap == NULL) {
61 DosFreeMem(pSharedMem);
62 dprintf(("InitializeSharedHeap: _ucreate failed!"));
63 return FALSE;
64 }
65 for(int i=0;i<INCR_HEAPSIZE/PAGE_SIZE;i++) {
66 pageBitmap[i] = 1; //mark as committed
67 }
68 }
69 else {
70 if(DosGetSharedMem(pSharedMem, PAG_READ|PAG_WRITE) != 0) {
71 dprintf(("InitializeSharedHeap: DosGetSharedMem failed!"));
72 return FALSE;
73 }
74 if(_uopen(sharedHeap) != 0) {
75 dprintf(("InitializeSharedHeap: unable to open shared heap!"));
76 return FALSE;
77 }
78 }
79 refCount++;
80 return TRUE;
81}
82//******************************************************************************
83//******************************************************************************
84void DestroySharedHeap()
85{
86 dprintf(("KERNEL32: DestroySharedHeap %d", refCount));
87 if(--refCount == 0) {
88 if(sharedHeap) {
89 _uclose(sharedHeap);
90 _udestroy(sharedHeap, _FORCE);
91 sharedHeap = NULL;
92 }
93 if(pSharedMem) {
94 DosFreeMem(pSharedMem);
95 pSharedMem = NULL;
96 }
97 }
98 else {
99 _uclose(sharedHeap);
100 }
101}
102//******************************************************************************
103//******************************************************************************
104ULONG GetPageRangeFree(ULONG pageoffset)
105{
106 dprintf(("KERNEL32: GetPageRangeFree(%08xh)\n",
107 pageoffset));
108
109 for(int i=pageoffset;i<MAX_HEAPPAGES;i++) {
110 if(pageBitmap[i] == 1) {
111 break;
112 }
113 }
114 return i-pageoffset;
115}
116//******************************************************************************
117//******************************************************************************
118void * _LNK_CONV getmoreShared(Heap_t pHeap, size_t *size, int *clean)
119{
120 APIRET rc;
121 ULONG newsize;
122 PVOID newblock;
123
124 dprintf(("KERNEL32: getmoreShared(%08xh, %08xh, %08xh)\n",
125 pHeap,
126 *size,
127 *clean));
128
129 /* round the size up to a multiple of 4K */
130 // *size = (*size / 4096) * 4096 + 4096;
131 // @@@PH speed improvement
132 *size = (*size + 4096) & 0xFFFFF000;
133 *size = max(*size, INCR_HEAPSIZE);
134
135 for(int i=0;i<MAX_HEAPPAGES;i++)
136 {
137 int nrpagesfree = GetPageRangeFree(i);
138 if(nrpagesfree >= *size/PAGE_SIZE) {
139 newblock = (PVOID)((ULONG)pSharedMem + i*PAGE_SIZE);
140 rc = DosSetMem(newblock, *size, PAG_READ|PAG_WRITE|PAG_COMMIT);
141 if(rc != 0) {
142 dprintf(("getmoreShared: DosSetMem failed with %d", rc));
143 return NULL;
144 }
145 for(int j=0;j < *size/PAGE_SIZE; j++)
146 {
147 pageBitmap[i+j] = 1; //mark as committed
148 }
149
150 *clean = _BLOCK_CLEAN;
151 dprintf(("KERNEL32: getmoreShared %x %d", newblock, *size));
152 return newblock;
153 }
154 if(nrpagesfree)
155 i += nrpagesfree-1;
156 }
157 dprintf(("KERNEL32: getmoreShared NOTHING LEFT (%d)", *size));
158 return NULL;
159}
160//******************************************************************************
161//******************************************************************************
162void _LNK_CONV releaseShared(Heap_t pHeap, void *block, size_t size)
163{
164 ULONG pagenr;
165
166 dprintf(("KERNEL32: releaseShared %x %d", block, size));
167 DosSetMem(block, size, PAG_READ|PAG_WRITE|PAG_DECOMMIT);
168
169 pagenr = (ULONG)block - (ULONG)pSharedMem;
170 pagenr /= PAGE_SIZE;
171 for(int i=pagenr;i<pagenr+size/PAGE_SIZE;i++) {
172 pageBitmap[i] = 0; //mark as decommitted
173 }
174}
175//******************************************************************************
176//******************************************************************************
177DWORD HeapGetSharedMemBase()
178{
179 dprintf(("KERNEL32: HeapGetSharedMemBase()\n"));
180 return (DWORD) pSharedMem;
181}
182//******************************************************************************
183//******************************************************************************
Note: See TracBrowser for help on using the repository browser.