From 55d615e06c127f6a41a0923210f7853886729b26 Mon Sep 17 00:00:00 2001 From: sof Date: Mon, 18 Jan 1999 09:20:08 +0000 Subject: [PATCH] [project @ 1999-01-18 09:20:08 by sof] 'Native' Wni32 implementation of getMBlock(). Also added a Win32 impl. of freeMBlock() in case that ever should become useful. --- ghc/rts/MBlock.c | 140 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 113 insertions(+), 27 deletions(-) diff --git a/ghc/rts/MBlock.c b/ghc/rts/MBlock.c index c9933d0..249493a 100644 --- a/ghc/rts/MBlock.c +++ b/ghc/rts/MBlock.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: MBlock.c,v 1.4 1999/01/14 18:31:17 sof Exp $ + * $Id: MBlock.c,v 1.5 1999/01/18 09:20:08 sof Exp $ * * MegaBlock Allocator Interface. This file contains all the dirty * architecture-dependent hackery required to get a chunk of aligned @@ -48,11 +48,6 @@ */ #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 @@ -70,6 +65,8 @@ getMBlock(void) return getMBlocks(1); } +#ifndef _WIN32 + void * getMBlocks(nat n) { @@ -85,29 +82,8 @@ getMBlocks(nat n) close(fd); } #else -# ifdef _WIN32 - { - /* Note: on 95, the legal range for next_request is: [0x00400000, 0x7fffffff] - under NT it is: [0x00010000, 0x7fffffff] - - We start allocating at 0x50000000, hopefully that's not conflicting with - others.. (ToDo: have the allocator try to gracefully rebase itself in - case our initial guess is conflicting with others.) - */ - ret = VirtualAlloc(next_request, size, MEM_RESERVE | MEM_COMMIT , PAGE_READWRITE); - if (!ret) { -# ifdef DEBUG - fprintf(stderr, "getMBlocks: VirtualAlloc failed with: %d\n", GetLastError()); -# endif - ret =(void*)-1; - - } - return ret; - } -# else ret = mmap(next_request, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); -# endif #endif if (ret == (void *)-1) { @@ -130,3 +106,113 @@ 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). + +*/ + +void * +getMBlocks(nat n) +{ + static char* base_non_committed = (char*)0; + static char* base_mblocks = (char*)0; + static char* next_request = (char*)0; + void* ret = (void*)0; + + lnat size = MBLOCK_SIZE * n; + + /* Reserve VM 128M at the time to try to minimise the slop cost. */ +#define SIZE_RESERVED_POOL ( 128 * 1024 * 1024 ) + + if ( (base_non_committed == 0) || + (next_request + size > base_non_committed + SIZE_RESERVED_POOL) ) { + base_non_committed = VirtualAlloc ( NULL + , SIZE_RESERVED_POOL + , MEM_RESERVE + , PAGE_READWRITE + ); + if ( base_non_committed == 0 ) { +# ifdef 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)base_non_committed & (unsigned)0xfff00000) + 0x100000; +# 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) ) { +# ifdef 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) { +# ifdef 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 -- 1.7.10.4