/* -----------------------------------------------------------------------------
- * $Id: MBlock.c,v 1.2 1998/12/02 13:28:28 simonm 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
*/
#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
/* ToDo: memory locations on other architectures */
#endif
+lnat mblocks_allocated = 0;
+
void *
getMBlock(void)
{
return getMBlocks(1);
}
+#ifndef _WIN32
+
void *
getMBlocks(nat n)
{
close(fd);
}
#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) {
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).
+
+*/
+
+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