1 /* -----------------------------------------------------------------------------
2 * $Id: MBlock.c,v 1.7 1999/01/25 11:55:06 sof Exp $
4 * MegaBlock Allocator Interface. This file contains all the dirty
5 * architecture-dependent hackery required to get a chunk of aligned
6 * memory from the operating system.
8 * ---------------------------------------------------------------------------*/
10 #define NON_POSIX_SOURCE
16 #include "BlockAlloc.h"
22 #ifdef HAVE_SYS_TYPES_H
23 #include <sys/types.h>
26 #ifdef HAVE_SYS_MMAN_H
34 #if cygwin32_TARGET_OS
38 #if freebsd2_TARGET_OS || freebsd3_TARGET_OS
39 /* Executable is loaded from 0x0
40 * Shared libraries are loaded at 0x2000000
41 * Stack is at the top of the address space. The kernel probably owns
42 * 0x8000000 onwards, so we'll pick 0x5000000.
44 #define ASK_FOR_MEM_AT 0x50000000
49 #define ASK_FOR_MEM_AT 0x50000000
51 #elif solaris2_TARGET_OS
53 #define ASK_FOR_MEM_AT 0x50000000
57 #define ASK_FOR_MEM_AT 0x50000000
60 /* doesn't matter, we use a reserve/commit algorithm */
63 #error Dont know where to get memory from on this architecture
64 /* ToDo: memory locations on other architectures */
67 lnat mblocks_allocated = 0;
80 static caddr_t next_request = (caddr_t)ASK_FOR_MEM_AT;
82 lnat size = MBLOCK_SIZE * n;
84 #ifdef solaris2_TARGET_OS
86 int fd = open("/dev/zero",O_RDONLY);
87 ret = mmap(next_request, size, PROT_READ | PROT_WRITE,
88 MAP_FIXED | MAP_PRIVATE, fd, 0);
92 ret = mmap(next_request, size, PROT_READ | PROT_WRITE,
93 MAP_ANON | MAP_PRIVATE, -1, 0);
96 if (ret == (void *)-1) {
97 if (errno == ENOMEM) {
98 barf("getMBlock: out of memory");
100 barf("GetMBlock: mmap failed");
104 if (((W_)ret & MBLOCK_MASK) != 0) {
105 barf("GetMBlock: misaligned block returned");
108 IF_DEBUG(gc,fprintf(stderr,"Allocated %d megablock(s) at %x\n",n,(nat)ret));
110 next_request += size;
112 mblocks_allocated += n;
120 On Win32 platforms we make use of the two-phased virtual memory API
121 to allocate mega blocks. We proceed as follows:
123 Reserve a large chunk of VM (128M at the time), but don't supply a
124 base address that's aligned on a MB boundary. Instead we round up to the
125 nearest from the chunk of VM we're given back from the OS (at the
126 moment we just leave the 'slop' at the beginning of the reserved
127 chunk unused - ToDo: reuse it .)
129 Reserving memory doesn't allocate physical storage (not even in the
130 page file), this is done by committing pages (or mega-blocks in
138 static char* base_non_committed = (char*)0;
139 static char* base_mblocks = (char*)0;
140 static char* next_request = (char*)0;
141 void* ret = (void*)0;
143 lnat size = MBLOCK_SIZE * n;
145 /* Reserve VM 128M at the time to try to minimise the slop cost. */
146 #define SIZE_RESERVED_POOL ( 128 * 1024 * 1024 )
148 if ( (base_non_committed == 0) ||
149 (next_request + size > base_non_committed + SIZE_RESERVED_POOL) ) {
150 base_non_committed = VirtualAlloc ( NULL
155 if ( base_non_committed == 0 ) {
157 fprintf(stderr, "getMBlocks: VirtualAlloc failed with: %d\n", GetLastError());
161 /* The returned pointer is not aligned on a mega-block boundary. Make it. */
162 base_mblocks = (char*)((unsigned)base_non_committed & (unsigned)0xfff00000) + 0x100000;
164 fprintf(stderr, "Dropping %d bytes off of 128M chunk\n",
165 (unsigned)base_mblocks - (unsigned)base_non_committed);
168 if ( ((char*)base_mblocks + size) > ((char*)base_non_committed + SIZE_RESERVED_POOL) ) {
170 fprintf(stderr, "oops, committed too small a region to start with.");
174 next_request = base_mblocks;
178 /* Commit the mega block(s) to phys mem */
179 if ( ret != (void*)-1 ) {
180 ret = VirtualAlloc(next_request, size, MEM_COMMIT, PAGE_READWRITE);
183 fprintf(stderr, "getMBlocks: VirtualAlloc failed with: %d\n", GetLastError());
189 if (((W_)ret & MBLOCK_MASK) != 0) {
190 barf("GetMBlock: misaligned block returned");
193 IF_DEBUG(gc,fprintf(stderr,"Allocated %d megablock(s) at %x\n",n,(nat)ret));
195 next_request = (char*)next_request + size;
197 mblocks_allocated += n;
202 /* Hand back the physical memory that is allocated to a mega-block.
203 ToDo: chain the released mega block onto some list so that
204 getMBlocks() can get at it.
210 freeMBlock(void* p, nat n)
214 rc = VirtualFree(p, n * MBLOCK_SIZE , MEM_DECOMMIT );
218 fprintf(stderr, "freeMBlocks: VirtualFree failed with: %d\n", GetLastError());