1 /* -----------------------------------------------------------------------------
2 * $Id: MBlock.c,v 1.8 1999/01/26 10:41:20 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
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;
79 static caddr_t next_request = (caddr_t)ASK_FOR_MEM_AT;
81 lnat size = MBLOCK_SIZE * n;
83 #ifdef solaris2_TARGET_OS
85 int fd = open("/dev/zero",O_RDONLY);
86 ret = mmap(next_request, size, PROT_READ | PROT_WRITE,
87 MAP_FIXED | MAP_PRIVATE, fd, 0);
91 ret = mmap(next_request, size, PROT_READ | PROT_WRITE,
92 MAP_ANON | MAP_PRIVATE, -1, 0);
95 if (ret == (void *)-1) {
96 if (errno == ENOMEM) {
97 barf("getMBlock: out of memory");
99 barf("GetMBlock: mmap failed");
103 if (((W_)ret & MBLOCK_MASK) != 0) {
104 barf("GetMBlock: misaligned block returned");
107 IF_DEBUG(gc,fprintf(stderr,"Allocated %d megablock(s) at %x\n",n,(nat)ret));
109 next_request += size;
111 mblocks_allocated += n;
119 On Win32 platforms we make use of the two-phased virtual memory API
120 to allocate mega blocks. We proceed as follows:
122 Reserve a large chunk of VM (128M at the time), but don't supply a
123 base address that's aligned on a MB boundary. Instead we round up to the
124 nearest from the chunk of VM we're given back from the OS (at the
125 moment we just leave the 'slop' at the beginning of the reserved
126 chunk unused - ToDo: reuse it .)
128 Reserving memory doesn't allocate physical storage (not even in the
129 page file), this is done by committing pages (or mega-blocks in
137 static char* base_non_committed = (char*)0;
138 static char* base_mblocks = (char*)0;
139 static char* next_request = (char*)0;
140 void* ret = (void*)0;
142 lnat size = MBLOCK_SIZE * n;
144 /* Reserve VM 128M at the time to try to minimise the slop cost. */
145 #define SIZE_RESERVED_POOL ( 128 * 1024 * 1024 )
147 if ( (base_non_committed == 0) ||
148 (next_request + size > base_non_committed + SIZE_RESERVED_POOL) ) {
149 base_non_committed = VirtualAlloc ( NULL
154 if ( base_non_committed == 0 ) {
156 fprintf(stderr, "getMBlocks: VirtualAlloc failed with: %d\n", GetLastError());
160 /* The returned pointer is not aligned on a mega-block boundary. Make it. */
161 base_mblocks = (char*)((unsigned)base_non_committed & (unsigned)0xfff00000) + 0x100000;
163 fprintf(stderr, "Dropping %d bytes off of 128M chunk\n",
164 (unsigned)base_mblocks - (unsigned)base_non_committed);
167 if ( ((char*)base_mblocks + size) > ((char*)base_non_committed + SIZE_RESERVED_POOL) ) {
169 fprintf(stderr, "oops, committed too small a region to start with.");
173 next_request = base_mblocks;
177 /* Commit the mega block(s) to phys mem */
178 if ( ret != (void*)-1 ) {
179 ret = VirtualAlloc(next_request, size, MEM_COMMIT, PAGE_READWRITE);
182 fprintf(stderr, "getMBlocks: VirtualAlloc failed with: %d\n", GetLastError());
188 if (((W_)ret & MBLOCK_MASK) != 0) {
189 barf("GetMBlock: misaligned block returned");
192 IF_DEBUG(gc,fprintf(stderr,"Allocated %d megablock(s) at %x\n",n,(nat)ret));
194 next_request = (char*)next_request + size;
196 mblocks_allocated += n;
201 /* Hand back the physical memory that is allocated to a mega-block.
202 ToDo: chain the released mega block onto some list so that
203 getMBlocks() can get at it.
209 freeMBlock(void* p, nat n)
213 rc = VirtualFree(p, n * MBLOCK_SIZE , MEM_DECOMMIT );
217 fprintf(stderr, "freeMBlocks: VirtualFree failed with: %d\n", GetLastError());