]> granicus.if.org Git - gc/commitdiff
Allow to get memory via Win32 VirtualAlloc (USE_WINALLOC) on Cygwin
authorIvan Maidanski <ivmai@mail.ru>
Thu, 9 Feb 2012 15:56:48 +0000 (19:56 +0400)
committerIvan Maidanski <ivmai@mail.ru>
Thu, 9 Feb 2012 15:56:48 +0000 (19:56 +0400)
* README.macros (USE_WINALLOC): Document.
* include/private/gcconfig.h (USE_WINALLOC): Add comment.
* include/private/gcconfig.h (USE_MMAP): Explicitly undefine if
USE_WINALLOC.
* os_dep.c (GC_wince_get_mem): Move definition up to simplify ifdef.
* os_dep.c (GC_win32_get_mem): Test USE_WINALLOC instead of CYGWIN32;
test GLOBAL_ALLOC_TEST value only if MSWIN32.

doc/README.macros
include/private/gcconfig.h
os_dep.c

index e04037dc4d39e8f794aa7e4671fd2378610b56c6..195969cb9439a5444d832b0794bdb039be7e93b1 100644 (file)
@@ -279,6 +279,9 @@ USE_MUNMAP      Causes memory to be returned to the OS under the right
   Works under some Unix, Linux and Windows versions.
   Requires USE_MMAP except for Windows.
 
+USE_WINALLOC (Cygwin only)   Use Win32 VirtualAlloc (instead of sbrk or mmap)
+  to get new memory.  Useful if memory unmapping (USE_MUNMAP) is enabled.
+
 MUNMAP_THRESHOLD=<value>        Set the desired memory blocks unmapping
   threshold (the number of sequential garbage collections for which
   a candidate block for unmapping should remain free).
index ae820ca214892cc2bfc84cb8d6d4aaa59ce469bb..9bb29e3b5c27383746e89296ee0eac85f69798c3 100644 (file)
 #endif
 
 #if (defined(MSWIN32) || defined(MSWINCE)) && !defined(USE_WINALLOC)
+  /* USE_WINALLOC is only an option for Cygwin. */
 # define USE_WINALLOC
 #endif
 
+#ifdef USE_WINALLOC
+# undef USE_MMAP
+#endif
+
 #if defined(GC_DISABLE_INCREMENTAL) || defined(MANUAL_VDB)
 # undef GWW_VDB
 # undef MPROTECT_VDB
index 14cb2ebf32b8e63c207af47466314b81ea6280e4..d27f4657f59be5a4fe38408527ac37b24ebaccb9 100644 (file)
--- a/os_dep.c
+++ b/os_dep.c
@@ -2193,7 +2193,62 @@ void * os2_alloc(size_t bytes)
 
 # endif /* OS2 */
 
-#if defined(MSWIN32) || defined(CYGWIN32)
+#ifdef MSWINCE
+  ptr_t GC_wince_get_mem(word bytes)
+  {
+    ptr_t result = 0; /* initialized to prevent warning. */
+    word i;
+
+    /* Round up allocation size to multiple of page size */
+    bytes = (bytes + GC_page_size-1) & ~(GC_page_size-1);
+
+    /* Try to find reserved, uncommitted pages */
+    for (i = 0; i < GC_n_heap_bases; i++) {
+        if (((word)(-(signed_word)GC_heap_lengths[i])
+             & (GC_sysinfo.dwAllocationGranularity-1))
+            >= bytes) {
+            result = GC_heap_bases[i] + GC_heap_lengths[i];
+            break;
+        }
+    }
+
+    if (i == GC_n_heap_bases) {
+        /* Reserve more pages */
+        word res_bytes = (bytes + GC_sysinfo.dwAllocationGranularity-1)
+                         & ~(GC_sysinfo.dwAllocationGranularity-1);
+        /* If we ever support MPROTECT_VDB here, we will probably need to    */
+        /* ensure that res_bytes is strictly > bytes, so that VirtualProtect */
+        /* never spans regions.  It seems to be OK for a VirtualFree         */
+        /* argument to span regions, so we should be OK for now.             */
+        result = (ptr_t) VirtualAlloc(NULL, res_bytes,
+                                MEM_RESERVE | MEM_TOP_DOWN,
+                                GC_pages_executable ? PAGE_EXECUTE_READWRITE :
+                                                      PAGE_READWRITE);
+        if (HBLKDISPL(result) != 0) ABORT("Bad VirtualAlloc result");
+            /* If I read the documentation correctly, this can  */
+            /* only happen if HBLKSIZE > 64k or not a power of 2.       */
+        if (GC_n_heap_bases >= MAX_HEAP_SECTS) ABORT("Too many heap sections");
+        if (result == NULL) return NULL;
+        GC_heap_bases[GC_n_heap_bases] = result;
+        GC_heap_lengths[GC_n_heap_bases] = 0;
+        GC_n_heap_bases++;
+    }
+
+    /* Commit pages */
+    result = (ptr_t) VirtualAlloc(result, bytes, MEM_COMMIT,
+                              GC_pages_executable ? PAGE_EXECUTE_READWRITE :
+                                                    PAGE_READWRITE);
+#   undef IGNORE_PAGES_EXECUTABLE
+
+    if (result != NULL) {
+        if (HBLKDISPL(result) != 0) ABORT("Bad VirtualAlloc result");
+        GC_heap_lengths[i] += bytes;
+    }
+
+    return(result);
+  }
+
+#elif defined(USE_WINALLOC) || defined(CYGWIN32)
 
 # ifdef USE_GLOBAL_ALLOC
 #   define GLOBAL_ALLOC_TEST 1
@@ -2214,16 +2269,19 @@ void * os2_alloc(size_t bytes)
   {
     ptr_t result;
 
-# ifdef CYGWIN32
+# ifndef USE_WINALLOC
     result = GC_unix_get_mem(bytes);
 # else
-    if (GLOBAL_ALLOC_TEST) {
+#   ifdef MSWIN32
+      if (GLOBAL_ALLOC_TEST) {
         /* VirtualAlloc doesn't like PAGE_EXECUTE_READWRITE.    */
         /* There are also unconfirmed rumors of other           */
         /* problems, so we dodge the issue.                     */
         result = (ptr_t) GlobalAlloc(0, bytes + HBLKSIZE);
         result = (ptr_t)(((word)result + HBLKSIZE - 1) & ~(HBLKSIZE-1));
-    } else {
+      } else
+#   endif
+    /* else */ {
         /* VirtualProtect only works on regions returned by a   */
         /* single VirtualAlloc call.  Thus we allocate one      */
         /* extra page, which will prevent merging of blocks     */
@@ -2257,7 +2315,7 @@ void * os2_alloc(size_t bytes)
                                                       PAGE_READWRITE);
 #       undef IGNORE_PAGES_EXECUTABLE
     }
-# endif /* !CYGWIN32 */
+# endif /* USE_WINALLOC */
     if (HBLKDISPL(result) != 0) ABORT("Bad VirtualAlloc result");
         /* If I read the documentation correctly, this can      */
         /* only happen if HBLKSIZE > 64k or not a power of 2.   */
@@ -2282,7 +2340,7 @@ void * os2_alloc(size_t bytes)
       }
     }
   }
-#endif /* MSWIN32 || CYGWIN32 */
+#endif /* USE_WINALLOC || CYGWIN32 */
 
 #ifdef AMIGA
 # define GC_AMIGA_AM
@@ -2290,63 +2348,6 @@ void * os2_alloc(size_t bytes)
 # undef GC_AMIGA_AM
 #endif
 
-
-#ifdef MSWINCE
-  ptr_t GC_wince_get_mem(word bytes)
-  {
-    ptr_t result = 0; /* initialized to prevent warning. */
-    word i;
-
-    /* Round up allocation size to multiple of page size */
-    bytes = (bytes + GC_page_size-1) & ~(GC_page_size-1);
-
-    /* Try to find reserved, uncommitted pages */
-    for (i = 0; i < GC_n_heap_bases; i++) {
-        if (((word)(-(signed_word)GC_heap_lengths[i])
-             & (GC_sysinfo.dwAllocationGranularity-1))
-            >= bytes) {
-            result = GC_heap_bases[i] + GC_heap_lengths[i];
-            break;
-        }
-    }
-
-    if (i == GC_n_heap_bases) {
-        /* Reserve more pages */
-        word res_bytes = (bytes + GC_sysinfo.dwAllocationGranularity-1)
-                         & ~(GC_sysinfo.dwAllocationGranularity-1);
-        /* If we ever support MPROTECT_VDB here, we will probably need to    */
-        /* ensure that res_bytes is strictly > bytes, so that VirtualProtect */
-        /* never spans regions.  It seems to be OK for a VirtualFree         */
-        /* argument to span regions, so we should be OK for now.             */
-        result = (ptr_t) VirtualAlloc(NULL, res_bytes,
-                                MEM_RESERVE | MEM_TOP_DOWN,
-                                GC_pages_executable ? PAGE_EXECUTE_READWRITE :
-                                                      PAGE_READWRITE);
-        if (HBLKDISPL(result) != 0) ABORT("Bad VirtualAlloc result");
-            /* If I read the documentation correctly, this can  */
-            /* only happen if HBLKSIZE > 64k or not a power of 2.       */
-        if (GC_n_heap_bases >= MAX_HEAP_SECTS) ABORT("Too many heap sections");
-        if (result == NULL) return NULL;
-        GC_heap_bases[GC_n_heap_bases] = result;
-        GC_heap_lengths[GC_n_heap_bases] = 0;
-        GC_n_heap_bases++;
-    }
-
-    /* Commit pages */
-    result = (ptr_t) VirtualAlloc(result, bytes, MEM_COMMIT,
-                              GC_pages_executable ? PAGE_EXECUTE_READWRITE :
-                                                    PAGE_READWRITE);
-#   undef IGNORE_PAGES_EXECUTABLE
-
-    if (result != NULL) {
-        if (HBLKDISPL(result) != 0) ABORT("Bad VirtualAlloc result");
-        GC_heap_lengths[i] += bytes;
-    }
-
-    return(result);
-  }
-#endif
-
 #ifdef USE_MUNMAP
 
 /* For now, this only works on Win32/WinCE and some Unix-like   */
@@ -2511,6 +2512,7 @@ GC_INNER void GC_unmap_gap(ptr_t start1, size_t bytes1, ptr_t start2,
       while (len != 0) {
           MEMORY_BASIC_INFORMATION mem_info;
           GC_word free_len;
+
           if (VirtualQuery(start_addr, &mem_info, sizeof(mem_info))
               != sizeof(mem_info))
               ABORT("Weird VirtualQuery result");