[project @ 1999-01-18 09:20:08 by sof]
authorsof <unknown>
Mon, 18 Jan 1999 09:20:08 +0000 (09:20 +0000)
committersof <unknown>
Mon, 18 Jan 1999 09:20:08 +0000 (09:20 +0000)
'Native' Wni32 implementation of getMBlock(). Also added a Win32 impl.
of freeMBlock() in case that ever should become useful.

ghc/rts/MBlock.c

index c9933d0..249493a 100644 (file)
@@ -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
  */
 #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