1 /* -----------------------------------------------------------------------------
2 * $Id: MBlock.c,v 1.6 1999/01/18 10:54:15 simonm 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
56 /* doesn't matter, we use a reserve/commit algorithm */
59 #error Dont know where to get memory from on this architecture
60 /* ToDo: memory locations on other architectures */
63 lnat mblocks_allocated = 0;
76 static caddr_t next_request = (caddr_t)ASK_FOR_MEM_AT;
78 lnat size = MBLOCK_SIZE * n;
80 #ifdef solaris2_TARGET_OS
82 int fd = open("/dev/zero",O_RDONLY);
83 ret = mmap(next_request, size, PROT_READ | PROT_WRITE,
84 MAP_FIXED | MAP_PRIVATE, fd, 0);
88 ret = mmap(next_request, size, PROT_READ | PROT_WRITE,
89 MAP_ANON | MAP_PRIVATE, -1, 0);
92 if (ret == (void *)-1) {
93 if (errno == ENOMEM) {
94 barf("getMBlock: out of memory");
96 barf("GetMBlock: mmap failed");
100 if (((W_)ret & MBLOCK_MASK) != 0) {
101 barf("GetMBlock: misaligned block returned");
104 IF_DEBUG(gc,fprintf(stderr,"Allocated %d megablock(s) at %x\n",n,(nat)ret));
106 next_request += size;
108 mblocks_allocated += n;
116 On Win32 platforms we make use of the two-phased virtual memory API
117 to allocate mega blocks. We proceed as follows:
119 Reserve a large chunk of VM (128M at the time), but don't supply a
120 base address that's aligned on a MB boundary. Instead we round up to the
121 nearest from the chunk of VM we're given back from the OS (at the
122 moment we just leave the 'slop' at the beginning of the reserved
123 chunk unused - ToDo: reuse it .)
125 Reserving memory doesn't allocate physical storage (not even in the
126 page file), this is done by committing pages (or mega-blocks in
134 static char* base_non_committed = (char*)0;
135 static char* base_mblocks = (char*)0;
136 static char* next_request = (char*)0;
137 void* ret = (void*)0;
139 lnat size = MBLOCK_SIZE * n;
141 /* Reserve VM 128M at the time to try to minimise the slop cost. */
142 #define SIZE_RESERVED_POOL ( 128 * 1024 * 1024 )
144 if ( (base_non_committed == 0) ||
145 (next_request + size > base_non_committed + SIZE_RESERVED_POOL) ) {
146 base_non_committed = VirtualAlloc ( NULL
151 if ( base_non_committed == 0 ) {
153 fprintf(stderr, "getMBlocks: VirtualAlloc failed with: %d\n", GetLastError());
157 /* The returned pointer is not aligned on a mega-block boundary. Make it. */
158 base_mblocks = (char*)((unsigned)base_non_committed & (unsigned)0xfff00000) + 0x100000;
160 fprintf(stderr, "Dropping %d bytes off of 128M chunk\n",
161 (unsigned)base_mblocks - (unsigned)base_non_committed);
164 if ( ((char*)base_mblocks + size) > ((char*)base_non_committed + SIZE_RESERVED_POOL) ) {
166 fprintf(stderr, "oops, committed too small a region to start with.");
170 next_request = base_mblocks;
174 /* Commit the mega block(s) to phys mem */
175 if ( ret != (void*)-1 ) {
176 ret = VirtualAlloc(next_request, size, MEM_COMMIT, PAGE_READWRITE);
179 fprintf(stderr, "getMBlocks: VirtualAlloc failed with: %d\n", GetLastError());
185 if (((W_)ret & MBLOCK_MASK) != 0) {
186 barf("GetMBlock: misaligned block returned");
189 IF_DEBUG(gc,fprintf(stderr,"Allocated %d megablock(s) at %x\n",n,(nat)ret));
191 next_request = (char*)next_request + size;
193 mblocks_allocated += n;
198 /* Hand back the physical memory that is allocated to a mega-block.
199 ToDo: chain the released mega block onto some list so that
200 getMBlocks() can get at it.
206 freeMBlock(void* p, nat n)
210 rc = VirtualFree(p, n * MBLOCK_SIZE , MEM_DECOMMIT );
214 fprintf(stderr, "freeMBlocks: VirtualFree failed with: %d\n", GetLastError());