X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Frts%2FMBlock.c;h=93478a295e3b55bc450acdb5b5c19b6b97d0d6ac;hb=c1d0aa931d8468c5fc02f069f2a5f32b057f139c;hp=9f0e89b5e8621a905364c138d95024cfe1910f82;hpb=5cc57129f941a8197e58f865cd93491c3a72a078;p=ghc-hetmet.git diff --git a/ghc/rts/MBlock.c b/ghc/rts/MBlock.c index 9f0e89b..93478a2 100644 --- a/ghc/rts/MBlock.c +++ b/ghc/rts/MBlock.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: MBlock.c,v 1.31 2002/10/21 12:42:31 simonmar Exp $ + * $Id: MBlock.c,v 1.42 2002/12/11 15:36:42 simonmar Exp $ * * (c) The GHC Team 1998-1999 * @@ -38,6 +38,9 @@ #if HAVE_WINDOWS_H #include #endif +#if darwin_TARGET_OS +#include +#endif #include @@ -47,13 +50,9 @@ lnat mblocks_allocated = 0; The MBlock Map: provides our implementation of HEAP_ALLOCED() -------------------------------------------------------------------------- */ -StgWord8 mblock_map[4096]; // initially all zeros - -static void -mblockIsHeap (void *p) -{ - mblock_map[((StgWord)p & ~MBLOCK_MASK) >> MBLOCK_SHIFT] = 1; -} +#ifdef MBLOCK_MAP_SIZE +StgWord8 mblock_map[MBLOCK_MAP_SIZE]; // initially all zeros +#endif /* ----------------------------------------------------------------------------- Allocate new mblock(s) @@ -95,23 +94,47 @@ my_mmap (void *addr, int size) #ifdef solaris2_TARGET_OS { int fd = open("/dev/zero",O_RDONLY); - ret = mmap(addr, size, PROT_READ | PROT_WRITE, - MAP_FIXED | MAP_PRIVATE, fd, 0); + ret = mmap(addr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); close(fd); } #elif hpux_TARGET_OS ret = mmap(addr, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); #elif darwin_TARGET_OS - ret = mmap(addr, size, PROT_READ | PROT_WRITE, - MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); + // Without MAP_FIXED, Apple's mmap ignores addr. + // With MAP_FIXED, it overwrites already mapped regions, whic + // mmap(0, ... MAP_FIXED ...) is worst of all: It unmaps the program text + // and replaces it with zeroes, causing instant death. + // This behaviour seems to be conformant with IEEE Std 1003.1-2001. + // Let's just use the underlying Mach Microkernel calls directly, + // they're much nicer. + + kern_return_t err; + ret = addr; + if(addr) // try to allocate at adress + err = vm_allocate(mach_task_self(),(vm_address_t*) &ret, size, FALSE); + if(!addr || err) // try to allocate anywhere + err = vm_allocate(mach_task_self(),(vm_address_t*) &ret, size, TRUE); + + if(err) // don't know what the error codes mean exactly + barf("memory allocation failed (requested %d bytes)", size); + else + vm_protect(mach_task_self(),ret,size,FALSE,VM_PROT_READ|VM_PROT_WRITE); #else - ret = mmap(addr, size, PROT_READ | PROT_WRITE, + ret = mmap(addr, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0); #endif + if (ret == (void *)-1) { + if (errno == ENOMEM) { + barf("out of memory (requested %d bytes)", size); + } else { + barf("getMBlock: mmap failed"); + } + } + return ret; -} +} // Implements the general case: allocate a chunk of memory of 'size' // mblocks. @@ -126,9 +149,6 @@ gen_map_mblocks (int size) // it (unmap the rest). size += MBLOCK_SIZE; ret = my_mmap(0, size); - if (ret == (void *)-1) { - barf("gen_map_mblocks: mmap failed"); - } // unmap the slop bits around the chunk we allocated slop = (W_)ret & MBLOCK_MASK; @@ -140,6 +160,9 @@ gen_map_mblocks (int size) barf("gen_map_mblocks: munmap failed"); } + // ToDo: if we happened to get an aligned block, then don't + // unmap the excess, just use it. + // next time, try after the block we just got. ret += MBLOCK_SIZE - slop; return ret; @@ -162,22 +185,13 @@ getMBlocks(nat n) ret = gen_map_mblocks(size); } else { ret = my_mmap(next_request, size); - - if (ret == (void *)-1) { - if (errno == ENOMEM) { - belch("out of memory (requested %d bytes)", n * BLOCK_SIZE); - stg_exit(EXIT_FAILURE); - } else { - barf("getMBlock: mmap failed"); - } - } if (((W_)ret & MBLOCK_MASK) != 0) { // misaligned block! -#ifdef DEBUG - belch("getMBlock: misaligned block %p returned when allocating %d megablock(s) at %p", ret, n, next_request); +#if 0 // defined(DEBUG) + belch("warning: getMBlock: misaligned block %p returned when allocating %d megablock(s) at %p", ret, n, next_request); #endif - + // unmap this block... if (munmap(ret, size) == -1) { barf("getMBlock: munmap failed"); @@ -188,13 +202,14 @@ getMBlocks(nat n) } // Next time, we'll try to allocate right after the block we just got. + // ToDo: check that we haven't already grabbed the memory at next_request next_request = ret + size; IF_DEBUG(gc,fprintf(stderr,"Allocated %d megablock(s) at %p\n",n,ret)); // fill in the table for (i = 0; i < n; i++) { - mblockIsHeap( ret + i * MBLOCK_SIZE ); + MARK_HEAP_ALLOCED( ret + i * MBLOCK_SIZE ); } mblocks_allocated += n; @@ -234,6 +249,7 @@ getMBlocks(nat n) static char* base_mblocks = (char*)0; static char* next_request = (char*)0; void* ret = (void*)0; + int i; lnat size = MBLOCK_SIZE * n; @@ -296,7 +312,7 @@ getMBlocks(nat n) // fill in the table for (i = 0; i < n; i++) { - mblockIsHeap( ret + i * MBLOCK_SIZE ); + MARK_HEAP_ALLOCED ( ret + i * MBLOCK_SIZE ); } return ret;