X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Frts%2FMBlock.c;h=eae83d2dc5fb1647454f998876c442044f8d26f5;hb=f98aaf1088d0b654ebf6c887c7dbebe5bb6f5f5f;hp=61bbbf7f9be280e577930ac0fbba94ba53e98a58;hpb=438596897ebbe25a07e1c82085cfbc5bdb00f09e;p=ghc-hetmet.git diff --git a/ghc/rts/MBlock.c b/ghc/rts/MBlock.c index 61bbbf7..eae83d2 100644 --- a/ghc/rts/MBlock.c +++ b/ghc/rts/MBlock.c @@ -1,5 +1,7 @@ /* ----------------------------------------------------------------------------- - * $Id: MBlock.c,v 1.2 1998/12/02 13:28:28 simonm Exp $ + * $Id: MBlock.c,v 1.18 2000/09/06 11:12:07 rrt 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 @@ -23,19 +25,21 @@ #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 +#if freebsd2_TARGET_OS || freebsd_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 @@ -43,12 +47,13 @@ */ #define ASK_FOR_MEM_AT 0x50000000 -#elif linux_TARGET_OS -/* Any ideas? +#elif netbsd_TARGET_OS +/* NetBSD i386 shared libs are at 0x40000000 */ #define ASK_FOR_MEM_AT 0x50000000 - -#elif cygwin32_TARGET_OS +#elif openbsd_TARGET_OS +#define ASK_FOR_MEM_AT 0x50000000 +#elif linux_TARGET_OS /* Any ideas? */ #define ASK_FOR_MEM_AT 0x50000000 @@ -57,17 +62,31 @@ /* guess */ #define ASK_FOR_MEM_AT 0x50000000 +#elif osf3_TARGET_OS +/* guess */ +#define ASK_FOR_MEM_AT 0x50000000 + +#elif hpux_TARGET_OS +/* guess */ +#define ASK_FOR_MEM_AT 0x50000000 + +#elif _WIN32 +/* doesn't matter, we use a reserve/commit algorithm */ + #else #error Dont know where to get memory from on this architecture /* ToDo: memory locations on other architectures */ #endif +lnat mblocks_allocated = 0; + void * getMBlock(void) { return getMBlocks(1); } +#ifndef _WIN32 void * getMBlocks(nat n) { @@ -82,40 +101,12 @@ 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); #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) { @@ -134,5 +125,131 @@ getMBlocks(nat n) next_request += size; + mblocks_allocated += 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 128M at the time to try to minimise the slop cost. */ +#define SIZE_RESERVED_POOL ( 128 * 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) ) { +#ifdef ENABLE_WIN32_DLL_SUPPORT + if (base_non_committed) + barf("Windows programs can only use 128Mb of heap; sorry!"); +#endif + base_non_committed = VirtualAlloc ( NULL + , SIZE_RESERVED_POOL + , MEM_RESERVE + , PAGE_READWRITE + ); + if ( base_non_committed == 0 ) { +# if 1 /*def DEBUG*/ + fprintf(stderr, "getMBlocks: VirtualAlloc failed with: %d\n", GetLastError()); +# endif + 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, "Dropping %d bytes off of 128M chunk\n", + (unsigned)base_mblocks - (unsigned)base_non_committed); +# endif + + if ( ((char*)base_mblocks + size) > ((char*)base_non_committed + SIZE_RESERVED_POOL) ) { +# if 1 /*def DEBUG*/ + fprintf(stderr, "oops, committed too small a region to start with."); +# endif + 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) { +# if 1 /*def DEBUG*/ + fprintf(stderr, "getMBlocks: VirtualAlloc failed with: %d\n", GetLastError()); +# endif + ret=(void*)-1; + } + } + + if (((W_)ret & MBLOCK_MASK) != 0) { + barf("GetMBlock: misaligned block returned"); + } + + IF_DEBUG(gc,fprintf(stderr,"Allocated %d megablock(s) at %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