1 /* -----------------------------------------------------------------------------
2 * $Id: MBlock.c,v 1.5 1999/01/18 09:20:08 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
56 #error Dont know where to get memory from on this architecture
57 /* ToDo: memory locations on other architectures */
60 lnat mblocks_allocated = 0;
73 static caddr_t next_request = (caddr_t)ASK_FOR_MEM_AT;
75 lnat size = MBLOCK_SIZE * n;
77 #ifdef solaris2_TARGET_OS
79 int fd = open("/dev/zero",O_RDONLY);
80 ret = mmap(next_request, size, PROT_READ | PROT_WRITE,
81 MAP_FIXED | MAP_PRIVATE, fd, 0);
85 ret = mmap(next_request, size, PROT_READ | PROT_WRITE,
86 MAP_ANON | MAP_PRIVATE, -1, 0);
89 if (ret == (void *)-1) {
90 if (errno == ENOMEM) {
91 barf("getMBlock: out of memory");
93 barf("GetMBlock: mmap failed");
97 if (((W_)ret & MBLOCK_MASK) != 0) {
98 barf("GetMBlock: misaligned block returned");
101 IF_DEBUG(gc,fprintf(stderr,"Allocated %d megablock(s) at %x\n",n,(nat)ret));
103 next_request += size;
105 mblocks_allocated += n;
113 On Win32 platforms we make use of the two-phased virtual memory API
114 to allocate mega blocks. We proceed as follows:
116 Reserve a large chunk of VM (128M at the time), but don't supply a
117 base address that's aligned on a MB boundary. Instead we round up to the
118 nearest from the chunk of VM we're given back from the OS (at the
119 moment we just leave the 'slop' at the beginning of the reserved
120 chunk unused - ToDo: reuse it .)
122 Reserving memory doesn't allocate physical storage (not even in the
123 page file), this is done by committing pages (or mega-blocks in
131 static char* base_non_committed = (char*)0;
132 static char* base_mblocks = (char*)0;
133 static char* next_request = (char*)0;
134 void* ret = (void*)0;
136 lnat size = MBLOCK_SIZE * n;
138 /* Reserve VM 128M at the time to try to minimise the slop cost. */
139 #define SIZE_RESERVED_POOL ( 128 * 1024 * 1024 )
141 if ( (base_non_committed == 0) ||
142 (next_request + size > base_non_committed + SIZE_RESERVED_POOL) ) {
143 base_non_committed = VirtualAlloc ( NULL
148 if ( base_non_committed == 0 ) {
150 fprintf(stderr, "getMBlocks: VirtualAlloc failed with: %d\n", GetLastError());
154 /* The returned pointer is not aligned on a mega-block boundary. Make it. */
155 base_mblocks = (char*)((unsigned)base_non_committed & (unsigned)0xfff00000) + 0x100000;
157 fprintf(stderr, "Dropping %d bytes off of 128M chunk\n",
158 (unsigned)base_mblocks - (unsigned)base_non_committed);
161 if ( ((char*)base_mblocks + size) > ((char*)base_non_committed + SIZE_RESERVED_POOL) ) {
163 fprintf(stderr, "oops, committed too small a region to start with.");
167 next_request = base_mblocks;
171 /* Commit the mega block(s) to phys mem */
172 if ( ret != (void*)-1 ) {
173 ret = VirtualAlloc(next_request, size, MEM_COMMIT, PAGE_READWRITE);
176 fprintf(stderr, "getMBlocks: VirtualAlloc failed with: %d\n", GetLastError());
182 if (((W_)ret & MBLOCK_MASK) != 0) {
183 barf("GetMBlock: misaligned block returned");
186 IF_DEBUG(gc,fprintf(stderr,"Allocated %d megablock(s) at %x\n",n,(nat)ret));
188 next_request = (char*)next_request + size;
190 mblocks_allocated += n;
195 /* Hand back the physical memory that is allocated to a mega-block.
196 ToDo: chain the released mega block onto some list so that
197 getMBlocks() can get at it.
203 freeMBlock(void* p, nat n)
207 rc = VirtualFree(p, n * MBLOCK_SIZE , MEM_DECOMMIT );
211 fprintf(stderr, "freeMBlocks: VirtualFree failed with: %d\n", GetLastError());