windows/MemorySupport.cpp
Go to the documentation of this file.
1 /*----------------------------------------------------------------------------*/
2 /* */
3 /* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved. */
4 /* Copyright (c) 2005-2009 Rexx Language Association. All rights reserved. */
5 /* */
6 /* This program and the accompanying materials are made available under */
7 /* the terms of the Common Public License v1.0 which accompanies this */
8 /* distribution. A copy is also available at the following address: */
9 /* http://www.oorexx.org/license.html */
10 /* */
11 /* Redistribution and use in source and binary forms, with or */
12 /* without modification, are permitted provided that the following */
13 /* conditions are met: */
14 /* */
15 /* Redistributions of source code must retain the above copyright */
16 /* notice, this list of conditions and the following disclaimer. */
17 /* Redistributions in binary form must reproduce the above copyright */
18 /* notice, this list of conditions and the following disclaimer in */
19 /* the documentation and/or other materials provided with the distribution. */
20 /* */
21 /* Neither the name of Rexx Language Association nor the names */
22 /* of its contributors may be used to endorse or promote products */
23 /* derived from this software without specific prior written permission. */
24 /* */
25 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
26 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
27 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
28 /* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
29 /* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
30 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
31 /* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
32 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */
33 /* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
34 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
35 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
36 /* */
37 /*----------------------------------------------------------------------------*/
38 /******************************************************************************/
39 /* REXX Kernel winmem.c */
40 /* */
41 /* Windows memory management */
42 /******************************************************************************/
43 
44 #include "RexxCore.h"
45 #include "RexxMemory.hpp"
46 #include "ActivityManager.hpp"
47 #include "SystemInterpreter.hpp"
48 
49 // retrofit by IH
50 #define MEMSIZE 4194304 /* get pools in 4M chunks. */
51 #define PAGESIZE 4096
52 
53 /*********************************************************************/
54 /* */
55 /* Function: Allocate a block of memory suitable to pass back to */
56 /* another program as a return result */
57 /* */
58 /*********************************************************************/
60  sizeB_t Size ) /* size to allocate */
61 {
62  return (void *)GlobalAlloc(GMEM_FIXED, size_v(Size));
63 }
64 
65 
66 /*********************************************************************/
67 /* */
68 /* Function: Release a block of memory given to us by an outside */
69 /* agent as a return result */
70 /* */
71 /*********************************************************************/
73  void *MemoryBlock) /* pointer to the result memory */
74 {
75  /* free for DB2 2.1.1 version */
76  if (GlobalSize(MemoryBlock))
77  GlobalFree(MemoryBlock);
78  else
79  free(MemoryBlock); /* release this block */
80 }
81 
82 
83 /**
84  * Create a the initial memory pool for the interpreter.
85  *
86  * @param pool pointer for the returned pool.
87  *
88  * @return
89  */
91 {
92  MemorySegmentPool * newPool;
93  void *tmpPtr;
94  size_t segmentSize;
95  /* create the memory segemnt */
96  /* if already exists then this */
97  /* isn't a coldstart. */
98  tmpPtr = VirtualAlloc(NULL, MEMSIZE, MEM_RESERVE|MEM_TOP_DOWN, PAGE_READWRITE);
99  if (tmpPtr != NULL)
100  {
101  segmentSize = RXROUNDUP(SegmentSize, PAGESIZE);
102  newPool = (MemorySegmentPool *)tmpPtr;
103  /* Now commit the storage. */
104  tmpPtr = VirtualAlloc(tmpPtr, segmentSize, MEM_COMMIT, PAGE_READWRITE);
105  if (!tmpPtr) /* Error on commit? */
106  {
108  return NULL; /* return NULL. */
109  }
110 
111  /* Since memory may not be ready */
112  /* for a segment we keep it as a spar*/
113  /* and will give it to memory on */
114  /* 1st request for a new segment. */
115 
116  newPool->spareSegment = new (((char *)newPool) + MemorySegmentPoolOverhead) MemorySegment (segmentSize - MemorySegmentPoolOverhead);
117  /* compute actual usable space. */
118  newPool->uncommitted = MEMSIZE - segmentSize;
119 #ifdef _DEBUG
120  newPool->reserved = MEMSIZE;
121 #endif
122  /* compute starting point of next */
123  /* allocation. */
124  newPool->nextAlloc = ((char *)newPool) + segmentSize;
125  /* start allocating large segments */
126  /* from the end of the pool. */
127  newPool->nextLargeAlloc = ((char*) newPool) + MEMSIZE;
128 
129  new (newPool) MemorySegmentPool; /* Initialize as a segmentPool */
130  return newPool; /* newly created. */
131  }
132  else
133  {
135  }
136  return NULL;
137 }
138 
139 
140 void *MemorySegmentPool::operator new(size_t size, size_t minSize)
141 /*********************************************************************/
142 /* Function:: Create a new MemoryPool block, which is basically */
143 /* a new OS/2 Shared memory block. */
144 /* */
145 /*********************************************************************/
146 {
147  MemorySegmentPool *newPool;
148  void *tmpPtr;
149  size_t initialSegSize;
150  size_t poolSize;
151 
152  /* Add pool object overhead to minSiz*/
153  minSize += MemorySegmentPoolOverhead;
154  if (minSize > MEMSIZE) /* Asking for more than default pool */
155  /* compute actual request size. */
156  poolSize = RXROUNDUP(minSize + MemorySegmentPoolOverhead, PAGESIZE);
157  else
158  poolSize = MEMSIZE;
159  /* create another shared memory */
160  /* segment, unnamed, Gettable. */
161  /* and initialiiy uncommited. */
162 
163  tmpPtr = VirtualAlloc(NULL, poolSize, MEM_RESERVE|MEM_TOP_DOWN, PAGE_READWRITE);
164  if (!tmpPtr) /* Error on reserve? */
165  {
167  return NULL; /* return NULL. */
168  }
169  /* Need to commit some potion of */
170  /* new pool, so create a segment from*/
171  /* from it. */
172 
173  if (minSize < SegmentSize) /* need more than a segment? */
174  /* nope make a normal segment */
175  initialSegSize = RXROUNDUP(SegmentSize, PAGESIZE);
176  else
177  /* yup, commit enough for this alloc */
178  initialSegSize = RXROUNDUP(minSize, PAGESIZE);
179 
180  /* Now commit the storage. */
181  tmpPtr = VirtualAlloc(tmpPtr, initialSegSize, MEM_COMMIT, PAGE_READWRITE);
182  /* Since memory may not be ready */
183  /* for a segment we keep it as a spar*/
184  /* and will give it to memory on */
185  /* 1st request for a new segment. */
186  newPool = (MemorySegmentPool *) tmpPtr;
187  if (!tmpPtr) /* Error on commit? */
188  {
190  return NULL; /* return NULL. */
191  }
192 
193  newPool->spareSegment = new (((char *)newPool) + MemorySegmentPoolOverhead) MemorySegment (initialSegSize - MemorySegmentPoolOverhead);
194  /* compute actual usable space. */
195  newPool->uncommitted = poolSize - initialSegSize;
196 #ifdef _DEBUG
197  newPool->reserved = poolSize;
198 #endif
199  /* compute starting poin of next */
200  /* allocation. */
201  newPool->nextAlloc = ((char *)newPool) + initialSegSize;
202  // note: the whole code here is a duplicate of the code in the constructor...
203  // ...why not use the constructor?
204  /* start allocating large segments */
205  /* from the end of the pool. */
206  newPool->nextLargeAlloc = ((char*) newPool) + poolSize;
207  return newPool;
208 }
209 
211 /*********************************************************************/
212 /* Function:: Constructor for memoryPool block. */
213 /* set next to NULL, size to size, */
214 /* */
215 /*********************************************************************/
216 {
217  this->next = NULL; /* No next pointer right now */
218 }
219 
220 
222 /*********************************************************************/
223 /* Function:: Constructor for memoryPool block. */
224 /* set next to NULL, size to size, */
225 /* */
226 /*********************************************************************/
227 {
228  size_t segmentSize;
229  MemorySegment *newSeg;
230  MemorySegmentPool *newPool;
231  void *tmpPtr;
232 
233  /* Any spare segments left over */
234  /* from initial pool alloc? */
235  /* And big enough for this request? */
236  if (this->spareSegment && this->spareSegment->size() >= minSize)
237  {
238  newSeg = this->spareSegment; /* no longer have a spare */
239  this->spareSegment = NULL;
240  return newSeg; /* return this segment for allocation*/
241  }
242  segmentSize = RXROUNDUP(minSize, PAGESIZE); /* compute commit size */
243  /* enough space for request */
244  if (this->uncommitted >= segmentSize)
245  {
246  /* commit next portion */
247  tmpPtr = VirtualAlloc((void *)this->nextAlloc, segmentSize, MEM_COMMIT,PAGE_READWRITE);
248  this->nextAlloc = (char *)tmpPtr;
249  if (!tmpPtr)
250  {
252  }
253  /* Create new segment. */
254  newSeg = new (this->nextAlloc) MemorySegment (segmentSize);
255  this->uncommitted -= segmentSize; /* Adjust uncommitted amount */
256  this->nextAlloc += segmentSize; /* Adjust to next Allocation addr */
257  return newSeg;
258  }
259  else
260  {
261  newPool = new (minSize) MemorySegmentPool;
262  /* Did we get a new Pool? */
263  if (newPool)
264  {
265  // make sure the memory object knows we've added a new pool to the set
266  memoryObject.memoryPoolAdded(newPool); // tell the memory object we have a new pool
267  this->next = newPool; /* Anchor it to end of chain */
268  return newPool->newSegment(minSize);
269  }
270  else
271  {
272  return NULL;
273  }
274  }
275 }
276 
278 /*********************************************************************/
279 /* Function: Allocate a large segment from the other end of the pool */
280 /*********************************************************************/
281 {
282  size_t segmentSize;
283  MemorySegment *newSeg;
284  MemorySegmentPool *newPool;
285  void *tmpPtr;
286 
287  /* Any spare segments left over */
288  /* from initial pool alloc? */
289  /* And big enough for this request? */
290  if (this->spareSegment && this->spareSegment->size() >= minSize)
291  {
292  newSeg = this->spareSegment; /* no longer have a spare */
293  this->spareSegment = NULL;
294  return newSeg; /* return this segment for allocation*/
295  }
296 
297  /* compute commit size */
298  segmentSize = RXROUNDUP(minSize, PAGESIZE);
299  /* enough space for request */
300  if (this->uncommitted >= segmentSize)
301  {
302  /* commit next portion */
303  tmpPtr = VirtualAlloc((void *)(this->nextLargeAlloc - segmentSize), segmentSize, MEM_COMMIT,PAGE_READWRITE);
304  this->nextLargeAlloc = (char *)tmpPtr;
305  if (!tmpPtr)
306  {
308  }
309  /* Create new segment. */
310  newSeg = new (this->nextLargeAlloc) MemorySegment (segmentSize);
311  this->uncommitted -= segmentSize; /* Adjust uncommitted amount */
312  // this->nextLargeAlloc does not have to be adjusted, will be correct
313  return newSeg;
314  }
315  else
316  {
317  newPool = new (minSize) MemorySegmentPool;
318  if (newPool) /* Did we get a new Pool? */
319  {
320  memoryObject.memoryPoolAdded(newPool);
321  this->next = newPool; /* Anchor it to end of chain */
322  return newPool->newLargeSegment(minSize);
323  }
324  else
325  {
326  return NULL;
327  }
328  }
329 }
330 
331 /* return a pointer to the next valid pool */
333 /*********************************************************************/
334 /* Function:: DosFreeMem this pool object */
335 /*********************************************************************/
336 {
337  VirtualFree(this, 0, MEM_RELEASE);
338 }
339 
340 
342 /*********************************************************************/
343 /* Function:: set the next pointer */
344 /*********************************************************************/
345 {
346  this->next = nextPool;
347 }
348 
void reportException(wholenumber_t error)
#define SegmentSize
#define MemorySegmentPoolOverhead
#define RXROUNDUP(n, to)
Definition: RexxCore.h:209
#define Error_System_resources
RexxMemory memoryObject
Definition: RexxMemory.cpp:85
MemorySegment * spareSegment
Definition: RexxMemory.hpp:133
MemorySegmentPool * next
Definition: RexxMemory.hpp:132
MemorySegment * newLargeSegment(size_t minSize)
MemorySegment * newSegment(size_t minSize)
static MemorySegmentPool * createPool()
MemorySegmentPool * nextPool()
Definition: RexxMemory.hpp:159
void setNext(MemorySegmentPool *nextPool)
void memoryPoolAdded(MemorySegmentPool *)
static void * allocateResultMemory(sizeB_t)
static void releaseResultMemory(void *)
#define size_v(X)
Definition: rexx.h:237
stringsizeB_t sizeB_t
Definition: rexx.h:248
#define PAGESIZE
#define MEMSIZE