X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Frts%2FMBlock.c;h=b0bd3c975824b127f090ac04cba18bade3172c66;hb=db61851c5472bf565cd1da900b33d6e033fd743d;hp=3c5225fe8a64741016eda7dd49dea64b89a5877a;hpb=4391e44f910ce579f269986faef9e5db8907a6c0;p=ghc-hetmet.git diff --git a/ghc/rts/MBlock.c b/ghc/rts/MBlock.c index 3c5225f..b0bd3c9 100644 --- a/ghc/rts/MBlock.c +++ b/ghc/rts/MBlock.c @@ -1,5 +1,7 @@ /* ----------------------------------------------------------------------------- - * $Id: MBlock.c,v 1.3 1999/01/13 17:25:40 simonm Exp $ + * $Id: MBlock.c,v 1.24 2001/10/26 11:49:19 sewardj Exp $ + * + * (c) The GHC Team 1998-1999 * * MegaBlock Allocator Interface. This file contains all the dirty * architecture-dependent hackery required to get a chunk of aligned @@ -7,7 +9,8 @@ * * ---------------------------------------------------------------------------*/ -#define NON_POSIX_SOURCE +/* This is non-posix compliant. */ +/* #include "PosixSource.h" */ #include "Rts.h" #include "RtsUtils.h" @@ -23,45 +26,20 @@ #include #endif -#ifdef HAVE_SYS_MMAN_H -#include +#ifndef mingw32_TARGET_OS +# ifdef HAVE_SYS_MMAN_H +# include +# endif #endif #ifdef HAVE_FCNTL_H #include #endif -#if cygwin32_TARGET_OS +#if HAVE_WINDOWS_H #include #endif -#if freebsd2_TARGET_OS || freebsd3_TARGET_OS -/* Executable is loaded from 0x0 - * Shared libraries are loaded at 0x2000000 - * Stack is at the top of the address space. The kernel probably owns - * 0x8000000 onwards, so we'll pick 0x5000000. - */ -#define ASK_FOR_MEM_AT 0x50000000 - -#elif linux_TARGET_OS -/* Any ideas? - */ -#define ASK_FOR_MEM_AT 0x50000000 - -#elif cygwin32_TARGET_OS -/* Any ideas? - */ -#define ASK_FOR_MEM_AT 0x50000000 - -#elif solaris2_TARGET_OS -/* guess */ -#define ASK_FOR_MEM_AT 0x50000000 - -#else -#error Dont know where to get memory from on this architecture -/* ToDo: memory locations on other architectures */ -#endif - lnat mblocks_allocated = 0; void * @@ -70,10 +48,11 @@ getMBlock(void) return getMBlocks(1); } +#ifndef _WIN32 void * getMBlocks(nat n) { - static caddr_t next_request = (caddr_t)ASK_FOR_MEM_AT; + static caddr_t next_request = (caddr_t)HEAP_BASE; caddr_t ret; lnat size = MBLOCK_SIZE * n; @@ -84,40 +63,15 @@ getMBlocks(nat n) MAP_FIXED | MAP_PRIVATE, fd, 0); close(fd); } +#elif hpux_TARGET_OS + ret = mmap(next_request, size, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); +#elif macosx_TARGET_OS + ret = mmap(next_request, size, PROT_READ | PROT_WRITE, + MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); #else -# ifdef _WIN32 - { - /* avoid using cygwin32's mmap implementation, it's buggy and - it's just as easy to do what we want to do directly. - */ - HANDLE hFile = (HANDLE)0xFFFFFFFF; - SECURITY_ATTRIBUTES sa; - HANDLE h; - - sa.nLength = sizeof (SECURITY_ATTRIBUTES); - sa.bInheritHandle = TRUE; - sa.lpSecurityDescriptor = 0; - - h = CreateFileMapping(hFile, &sa, PAGE_READWRITE, 0, size, NULL); - if ( h == 0 ) { -# ifdef DEBUG - fprintf(stderr, "getMBlocks: CreateFileMapping failed with: %d\n", GetLastError()); -# endif - ret=(void*)-1; - } else { - ret = MapViewOfFileEx (h, FILE_MAP_WRITE, 0, 0, size, next_request); - if ( ret != next_request ) { -# ifdef DEBUG - fprintf(stderr, "getMBlocks: MapViewOfFileEx failed with: %d\n", GetLastError()); -# endif - ret =(void*)-1; - } - } - } -# else ret = mmap(next_request, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); -# endif #endif if (ret == (void *)-1) { @@ -129,10 +83,10 @@ getMBlocks(nat n) } if (((W_)ret & MBLOCK_MASK) != 0) { - barf("GetMBlock: misaligned block returned"); + barf("GetMBlock: misaligned block %p returned when allocating %d megablock(s) at %p", ret, n, next_request); } - IF_DEBUG(gc,fprintf(stderr,"Allocated %d megablock(s) at %x\n",n,(nat)ret)); + IF_DEBUG(gc,fprintf(stderr,"Allocated %d megablock(s) at %p\n",n,ret)); next_request += size; @@ -140,3 +94,122 @@ getMBlocks(nat n) return ret; } + +#else /* _WIN32 */ + +/* + On Win32 platforms we make use of the two-phased virtual memory API + to allocate mega blocks. We proceed as follows: + + Reserve a large chunk of VM (128M at the time), but don't supply a + base address that's aligned on a MB boundary. Instead we round up to the + nearest from the chunk of VM we're given back from the OS (at the + moment we just leave the 'slop' at the beginning of the reserved + chunk unused - ToDo: reuse it .) + + Reserving memory doesn't allocate physical storage (not even in the + page file), this is done by committing pages (or mega-blocks in + our case). + +*/ + +char* base_non_committed = (char*)0; + +/* Reserve VM 256M at the time to try to minimise the slop cost. */ +#define SIZE_RESERVED_POOL ( 256 * 1024 * 1024 ) + +/* This predicate should be inlined, really. */ +/* TODO: this only works for a single chunk */ +int +is_heap_alloced(const void* x) +{ + return (((char*)(x) >= base_non_committed) && + ((char*)(x) <= (base_non_committed + SIZE_RESERVED_POOL))); +} + +void * +getMBlocks(nat n) +{ + static char* base_mblocks = (char*)0; + static char* next_request = (char*)0; + void* ret = (void*)0; + + lnat size = MBLOCK_SIZE * n; + + if ( (base_non_committed == 0) || + (next_request + size > base_non_committed + SIZE_RESERVED_POOL) ) { + if (base_non_committed) + barf("Windows programs can only use 256Mb of heap; sorry!"); + base_non_committed = VirtualAlloc ( NULL + , SIZE_RESERVED_POOL + , MEM_RESERVE + , PAGE_READWRITE + ); + if ( base_non_committed == 0 ) { + fprintf(stderr, "getMBlocks: VirtualAlloc failed with: %ld\n", GetLastError()); + ret=(void*)-1; + } else { + /* The returned pointer is not aligned on a mega-block boundary. Make it. */ + base_mblocks = (char*)((unsigned long)base_non_committed & (unsigned long)0xfff00000) + MBLOCK_SIZE; +# if 0 + fprintf(stderr, "getMBlocks: Dropping %d bytes off of 256M chunk\n", + (unsigned)base_mblocks - (unsigned)base_non_committed); +# endif + + if ( ((char*)base_mblocks + size) > ((char*)base_non_committed + SIZE_RESERVED_POOL) ) { + fprintf(stderr, "getMBlocks: oops, committed too small a region to start with."); + ret=(void*)-1; + } else { + next_request = base_mblocks; + } + } + } + /* Commit the mega block(s) to phys mem */ + if ( ret != (void*)-1 ) { + ret = VirtualAlloc(next_request, size, MEM_COMMIT, PAGE_READWRITE); + if (ret == NULL) { + fprintf(stderr, "getMBlocks: VirtualAlloc failed with: %ld\n", GetLastError()); + ret=(void*)-1; + } + } + + if (((W_)ret & MBLOCK_MASK) != 0) { + barf("getMBlocks: misaligned block returned"); + } + + if (ret == (void*)-1) { + barf("getMBlocks: unknown memory allocation failure on Win32."); + } + + IF_DEBUG(gc,fprintf(stderr,"Allocated %d megablock(s) at 0x%x\n",n,(nat)ret)); + next_request = (char*)next_request + size; + + mblocks_allocated += n; + + return ret; +} + +/* Hand back the physical memory that is allocated to a mega-block. + ToDo: chain the released mega block onto some list so that + getMBlocks() can get at it. + + Currently unused. +*/ +#if 0 +void +freeMBlock(void* p, nat n) +{ + BOOL rc; + + rc = VirtualFree(p, n * MBLOCK_SIZE , MEM_DECOMMIT ); + + if (rc == FALSE) { +# ifdef DEBUG + fprintf(stderr, "freeMBlocks: VirtualFree failed with: %d\n", GetLastError()); +# endif + } + +} +#endif + +#endif