]> granicus.if.org Git - gc/commitdiff
2009-10-01 Ivan Maidanski <ivmai@mail.ru>
authorivmai <ivmai>
Thu, 1 Oct 2009 12:48:38 +0000 (12:48 +0000)
committerIvan Maidanski <ivmai@mail.ru>
Tue, 26 Jul 2011 17:06:49 +0000 (21:06 +0400)
* dyn_load.c (GC_register_dynamic_libraries): Always use
lpMaximumApplicationAddress value for WinCE (even for old
versions).
* os_dep.c (VER_PLATFORM_WIN32_CE): Define if not in winbase.h.
* os_dep.c (GC_dont_query_stack_min): New global variable (only if
WinCE and THREADS).
* os_dep.c (GC_setpagesize): Adjust lpMaximumApplicationAddress
for WinCE (prior to version 6) if not _WIN32_WCE_EMULATION; set
GC_dont_query_stack_min for older WinCE (prior to version 5).
* win32_threads.c (GC_dont_query_stack_min): Declare.
* win32_threads.c (GC_get_stack_min): Rename the macro to
GC_wince_evaluate_stack_min for WinCE; update the comment.
* win32_threads.c (GC_push_stack_for, GC_get_next_stack): Use
GC_wince_evaluate_stack_min() instead of GC_get_stack_min() for
WinCE and don't update thread's last_stack_min value (only if
GC_dont_query_stack_min).
* win32_threads.c (GC_push_stack_for): Skip assertion for WinCE if
GC_dont_query_stack_min (since the evaluated stack_min value may
be incorrect if the stack is bigger than 64 KiB).

ChangeLog
dyn_load.c
os_dep.c
win32_threads.c

index 597cad81f27ad6b08a394e406108eb9e7b7750a7..46f2c88f1cedffe06a5d53cf59e3b34b30e755f2 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2009-10-01  Ivan Maidanski <ivmai@mail.ru>
+
+       * dyn_load.c (GC_register_dynamic_libraries): Always use
+       lpMaximumApplicationAddress value for WinCE (even for old
+       versions).
+       * os_dep.c (VER_PLATFORM_WIN32_CE): Define if not in winbase.h.
+       * os_dep.c (GC_dont_query_stack_min): New global variable (only if
+       WinCE and THREADS).
+       * os_dep.c (GC_setpagesize): Adjust lpMaximumApplicationAddress
+       for WinCE (prior to version 6) if not _WIN32_WCE_EMULATION; set
+       GC_dont_query_stack_min for older WinCE (prior to version 5).
+       * win32_threads.c (GC_dont_query_stack_min): Declare.
+       * win32_threads.c (GC_get_stack_min): Rename the macro to
+       GC_wince_evaluate_stack_min for WinCE; update the comment.
+       * win32_threads.c (GC_push_stack_for, GC_get_next_stack): Use
+       GC_wince_evaluate_stack_min() instead of GC_get_stack_min() for
+       WinCE and don't update thread's last_stack_min value (only if
+       GC_dont_query_stack_min).
+       * win32_threads.c (GC_push_stack_for): Skip assertion for WinCE if
+       GC_dont_query_stack_min (since the evaluated stack_min value may
+       be incorrect if the stack is bigger than 64 KiB).
+
 2009-10-01  Ivan Maidanski <ivmai@mail.ru>
 
        * gc_dlopen.c (GC_dlopen): Add function redirector (only if
index 1679ebc20b446ce461584bee7bcb885372838b93..8539172d84c5847e75c44433c09646795ac59dbd 100644 (file)
@@ -884,22 +884,17 @@ void GC_register_dynamic_libraries(void)
       if (GC_no_win32_dlls) return;
 #   endif
     base = limit = p = GC_sysinfo.lpMinimumApplicationAddress;
-    /* Note: -D_WIN32_WCE_EMULATION seems to be required for WinCE 6. */
-#   if defined(MSWINCE) && !defined(_WIN32_WCE_EMULATION)
-      /* Only the first 32 MB of address space belongs to the current process */
-      while (p < (LPVOID)0x02000000) {
+    while (p < GC_sysinfo.lpMaximumApplicationAddress) {
         result = VirtualQuery(p, &buf, sizeof(buf));
-        if (result == 0) {
+#       ifdef MSWINCE
+          if (result == 0) {
             /* Page is free; advance to the next possible allocation base */
             new_limit = (char *)
                 (((DWORD) p + GC_sysinfo.dwAllocationGranularity)
                  & ~(GC_sysinfo.dwAllocationGranularity-1));
-        } else
-#   else
-      while (p < GC_sysinfo.lpMaximumApplicationAddress) {
-        result = VirtualQuery(p, &buf, sizeof(buf));
-#   endif
-        {
+          } else
+#       endif
+        /* else */ {
             if (result != sizeof(buf)) {
                 ABORT("Weird VirtualQuery result");
             }
index 0a6b8d8fb7d804213bc811e9383974faf593d035..6fda51e90543e194423089d998a200b8aaca22a6 100644 (file)
--- a/os_dep.c
+++ b/os_dep.c
@@ -602,10 +602,41 @@ struct o32_obj {
 word GC_page_size = 0;
 
 # if defined(MSWIN32) || defined(MSWINCE)
+
+#   ifndef VER_PLATFORM_WIN32_CE
+#     define VER_PLATFORM_WIN32_CE 3
+#   endif
+
+#   if defined(MSWINCE) && defined(THREADS)
+      GC_bool GC_dont_query_stack_min = FALSE;
+#   endif
+
     void GC_setpagesize(void)
     {
       GetSystemInfo(&GC_sysinfo);
       GC_page_size = GC_sysinfo.dwPageSize;
+#     if defined(MSWINCE) && !defined(_WIN32_WCE_EMULATION)
+        {
+          OSVERSIONINFO verInfo;
+          /* Check the current WinCE version. */
+          verInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+          if (!GetVersionEx(&verInfo))
+            ABORT("GetVersionEx failed");
+          if (verInfo.dwPlatformId == VER_PLATFORM_WIN32_CE &&
+              verInfo.dwMajorVersion < 6) {
+            /* Only the first 32 MB of address space belongs to the     */
+            /* current process (unless WinCE 6.0+ or emulation).        */
+            GC_sysinfo.lpMaximumApplicationAddress = (LPVOID)((word)32 << 20);
+#           ifdef THREADS
+              /* On some old WinCE versions, it's observed that         */
+              /* VirtualQuery calls don't work properly when used to    */
+              /* get thread current stack committed minimum.            */
+              if (verInfo.dwMajorVersion < 5)
+                GC_dont_query_stack_min = TRUE;
+#           endif
+          }
+        }
+#     endif
     }
 
 # else
@@ -2590,7 +2621,7 @@ void GC_remove_protection(struct hblk *h, word nblocks, GC_bool is_ptrfree)
 # ifdef DARWIN
     /* Using vm_protect (mach syscall) over mprotect (BSD syscall) seems to
        decrease the likelihood of some of the problems described below. */
-    #include <mach/vm_map.h>
+#   include <mach/vm_map.h>
     static mach_port_t GC_task_self;
 #   define PROTECT(addr,len) \
         if(vm_protect(GC_task_self,(vm_address_t)(addr),(vm_size_t)(len), \
index 6bd8893682fcfb4a33d8b55bacfa2f21667e173e..b12742dd6ad7535ccb7b0d5404d2a2e3b7d9d2f1 100644 (file)
@@ -894,22 +894,20 @@ void GC_push_thread_structures(void)
 {
   GC_ASSERT(I_HOLD_LOCK());
 # ifndef GC_NO_DLLMAIN
-   if (GC_win32_dll_threads) {
-     /* Unlike the other threads implementations, the thread table here */
-     /* contains no pointers to the collectable heap.  Thus we have     */
-     /* no private structures we need to preserve.                      */
-#    ifdef GC_PTHREADS
-       {
-         int i; /* pthreads may keep a pointer in the thread exit value */
-         LONG my_max = GC_get_max_thread_index();
-
-         for (i = 0; i <= my_max; i++)
-           if (dll_thread_table[i].in_use)
-             GC_push_all((ptr_t)&(dll_thread_table[i].status),
-                         (ptr_t)(&(dll_thread_table[i].status)+1));
-       }
-#    endif
-   } else
+    if (GC_win32_dll_threads) {
+      /* Unlike the other threads implementations, the thread table here */
+      /* contains no pointers to the collectable heap.  Thus we have     */
+      /* no private structures we need to preserve.                      */
+#     ifdef GC_PTHREADS
+        int i; /* pthreads may keep a pointer in the thread exit value */
+        LONG my_max = GC_get_max_thread_index();
+
+        for (i = 0; i <= my_max; i++)
+          if (dll_thread_table[i].in_use)
+            GC_push_all((ptr_t)&(dll_thread_table[i].status),
+                        (ptr_t)(&(dll_thread_table[i].status)+1));
+#     endif
+    } else
 # endif
   /* else */ {
     GC_push_all((ptr_t)(GC_threads), (ptr_t)(GC_threads)+sizeof(GC_threads));
@@ -1076,54 +1074,60 @@ void GC_start_world(void)
   GC_please_stop = FALSE;
 }
 
-/* Note: -D_WIN32_WCE_EMULATION might to be required for WinCE 6.      */
-#if defined(MSWINCE) && !defined(_WIN32_WCE_EMULATION)
-  /* The VirtualQuery calls below won't work properly on WinCE, but     */
-  /* since each stack is restricted to an aligned 64K region of         */
-  /* virtual memory we can just take the next lowest multiple of 64K.   */
-# define GC_get_stack_min(s) (ptr_t)(((word)(s) - 1) & ~(word)0xFFFF)
-#else
+#ifdef MSWINCE
+  GC_bool GC_dont_query_stack_min; /* defined and set in os_dep.c */
+
+  /* The VirtualQuery calls below won't work properly on some old WinCE */
+  /* versions, but since each stack is restricted to an aligned 64 KiB  */
+  /* region of virtual memory we can just take the next lowest multiple */
+  /* of 64 KiB.  The result of this macro must not be used as its       */
+  /* argument later and must not be used as the lower bound for sp      */
+  /* check (since the stack may be bigger than 64 KiB).                 */
+# define GC_wince_evaluate_stack_min(s) \
+                        (ptr_t)(((word)(s) - 1) & ~(word)0xFFFF)
+#elif defined(GC_ASSERTIONS)
+# define GC_dont_query_stack_min FALSE
+#endif
 
-  /* A cache holding the results of the recent VirtualQuery call.       */
-  /* Protected by the allocation lock.                                  */
-  static ptr_t last_address = 0;
-  static MEMORY_BASIC_INFORMATION last_info;
+/* A cache holding the results of the recent VirtualQuery call. */
+/* Protected by the allocation lock.                            */
+static ptr_t last_address = 0;
+static MEMORY_BASIC_INFORMATION last_info;
 
-  /* Probe stack memory region (starting at "s") to find out its        */
-  /* lowest address (i.e. stack top).                                   */
-  /* S must be a mapped address inside the region, NOT the first        */
-  /* unmapped address.                                                  */
-  static ptr_t GC_get_stack_min(ptr_t s)
-  {
-    ptr_t bottom;
+/* Probe stack memory region (starting at "s") to find out its  */
+/* lowest address (i.e. stack top).                             */
+/* S must be a mapped address inside the region, NOT the first  */
+/* unmapped address.                                            */
+static ptr_t GC_get_stack_min(ptr_t s)
+{
+  ptr_t bottom;
 
-    GC_ASSERT(I_HOLD_LOCK());
-    if (s != last_address) {
-      VirtualQuery(s, &last_info, sizeof(last_info));
-      last_address = s;
-    }
-    do {
-      bottom = last_info.BaseAddress;
-      VirtualQuery(bottom - 1, &last_info, sizeof(last_info));
-      last_address = bottom - 1;
-    } while ((last_info.Protect & PAGE_READWRITE)
-             && !(last_info.Protect & PAGE_GUARD));
-    return(bottom);
+  GC_ASSERT(I_HOLD_LOCK());
+  if (s != last_address) {
+    VirtualQuery(s, &last_info, sizeof(last_info));
+    last_address = s;
   }
+  do {
+    bottom = last_info.BaseAddress;
+    VirtualQuery(bottom - 1, &last_info, sizeof(last_info));
+    last_address = bottom - 1;
+  } while ((last_info.Protect & PAGE_READWRITE)
+           && !(last_info.Protect & PAGE_GUARD));
+  return(bottom);
+}
 
-  /* Return true if the page at s has protections appropriate   */
-  /* for a stack page.                                          */
-  static GC_bool GC_may_be_in_stack(ptr_t s)
-  {
-    GC_ASSERT(I_HOLD_LOCK());
-    if (s != last_address) {
-      VirtualQuery(s, &last_info, sizeof(last_info));
-      last_address = s;
-    }
-    return (last_info.Protect & PAGE_READWRITE)
-            && !(last_info.Protect & PAGE_GUARD);
+/* Return true if the page at s has protections appropriate     */
+/* for a stack page.                                            */
+static GC_bool GC_may_be_in_stack(ptr_t s)
+{
+  GC_ASSERT(I_HOLD_LOCK());
+  if (s != last_address) {
+    VirtualQuery(s, &last_info, sizeof(last_info));
+    last_address = s;
   }
-#endif
+  return (last_info.Protect & PAGE_READWRITE)
+          && !(last_info.Protect & PAGE_GUARD);
+}
 
 STATIC void GC_push_stack_for(GC_thread thread)
 {
@@ -1194,10 +1198,19 @@ STATIC void GC_push_stack_for(GC_thread thread)
     /* taking advantage of the old value to avoid slow traversals       */
     /* of large stacks.                                                 */
     if (thread -> last_stack_min == ADDR_LIMIT) {
-      stack_min = GC_get_stack_min(activation_frame != NULL ?
+#     ifdef MSWINCE
+        if (GC_dont_query_stack_min) {
+          stack_min = GC_wince_evaluate_stack_min(activation_frame != NULL ?
                         (ptr_t)activation_frame : thread -> stack_base);
-      UNPROTECT_THREAD(thread);
-      thread -> last_stack_min = stack_min;
+          /* Keep last_stack_min value unmodified. */
+        } else
+#     endif
+      /* else */ {
+        stack_min = GC_get_stack_min(activation_frame != NULL ?
+                        (ptr_t)activation_frame : thread -> stack_base);
+        UNPROTECT_THREAD(thread);
+        thread -> last_stack_min = stack_min;
+      }
     } else {
       /* First, adjust the latest known minimum stack address if we     */
       /* are inside GC_call_with_gc_active().                           */
@@ -1210,28 +1223,25 @@ STATIC void GC_push_stack_for(GC_thread thread)
       if (sp < thread -> stack_base && sp >= thread -> last_stack_min) {
         stack_min = sp;
       } else {
-#       if defined(MSWINCE) && !defined(_WIN32_WCE_EMULATION)
-          stack_min = GC_get_stack_min(activation_frame != NULL ?
-                        (ptr_t)activation_frame : thread -> stack_base);
-#       else
-          /* In the current thread it is always safe to use sp value. */
-          if (GC_may_be_in_stack(thread -> id == me &&
-                                 sp < thread -> last_stack_min ?
-                                 sp : thread -> last_stack_min)) {
-            stack_min = last_info.BaseAddress;
-            /* Do not probe rest of the stack if sp is correct. */
-            if (sp < stack_min || sp >= thread->stack_base)
-              stack_min = GC_get_stack_min(thread -> last_stack_min);
-          } else {
-            /* Stack shrunk?  Is this possible? */
-            stack_min = GC_get_stack_min(thread -> stack_base);
-          }
-#       endif
+        /* In the current thread it is always safe to use sp value. */
+        if (GC_may_be_in_stack(thread -> id == me &&
+                               sp < thread -> last_stack_min ?
+                               sp : thread -> last_stack_min)) {
+          stack_min = last_info.BaseAddress;
+          /* Do not probe rest of the stack if sp is correct. */
+          if (sp < stack_min || sp >= thread->stack_base)
+            stack_min = GC_get_stack_min(thread -> last_stack_min);
+        } else {
+          /* Stack shrunk?  Is this possible? */
+          stack_min = GC_get_stack_min(thread -> stack_base);
+        }
         UNPROTECT_THREAD(thread);
         thread -> last_stack_min = stack_min;
       }
     }
-    GC_ASSERT(stack_min == GC_get_stack_min(thread -> stack_base)
+
+    GC_ASSERT(GC_dont_query_stack_min
+              || stack_min == GC_get_stack_min(thread -> stack_base)
               || (sp >= stack_min && stack_min < thread -> stack_base
                   && stack_min > GC_get_stack_min(thread -> stack_base)));
 
@@ -1400,35 +1410,38 @@ void GC_get_next_stack(char *start, char *limit,
   }
 
   GC_ASSERT(current_min > start);
-# if defined(MSWINCE) && !defined(_WIN32_WCE_EMULATION)
-    /* No need to maintain the latest known stack_min. */
-    *lo = GC_get_stack_min(current_min);
-# else
-    if (current_min > limit && !GC_may_be_in_stack(limit)) {
-      /* Skip the rest since the memory region at limit address is      */
-      /* not a stack (so the lowest address of the found stack would    */
-      /* be above the limit value anyway).                              */
-      *lo = ADDR_LIMIT;
+# ifdef MSWINCE
+    if (GC_dont_query_stack_min) {
+      *lo = GC_wince_evaluate_stack_min(current_min);
+      /* Keep last_stack_min value unmodified. */
       return;
     }
+# endif
 
-    /* Get the minimum address of the found stack by probing its memory */
-    /* region starting from the recent known minimum (if set).          */
-    if (*plast_stack_min == ADDR_LIMIT
-        || !GC_may_be_in_stack(*plast_stack_min)) {
-      /* Unsafe to start from last_stack_min value. */
-      *lo = GC_get_stack_min(current_min);
-    } else {
-      /* Use the recent value to optimize search for min address. */
-      *lo = GC_get_stack_min(*plast_stack_min);
-    }
+  if (current_min > limit && !GC_may_be_in_stack(limit)) {
+    /* Skip the rest since the memory region at limit address is        */
+    /* not a stack (so the lowest address of the found stack would      */
+    /* be above the limit value anyway).                                */
+    *lo = ADDR_LIMIT;
+    return;
+  }
 
-    /* Remember current stack_min value. */
-    if (thread != NULL) {
-      UNPROTECT_THREAD(thread);
-    }
-    *plast_stack_min = *lo;
-# endif
+  /* Get the minimum address of the found stack by probing its memory   */
+  /* region starting from the recent known minimum (if set).            */
+  if (*plast_stack_min == ADDR_LIMIT
+      || !GC_may_be_in_stack(*plast_stack_min)) {
+    /* Unsafe to start from last_stack_min value. */
+    *lo = GC_get_stack_min(current_min);
+  } else {
+    /* Use the recent value to optimize search for min address. */
+    *lo = GC_get_stack_min(*plast_stack_min);
+  }
+
+  /* Remember current stack_min value. */
+  if (thread != NULL) {
+    UNPROTECT_THREAD(thread);
+  }
+  *plast_stack_min = *lo;
 }
 
 #ifdef PARALLEL_MARK