From: ivmai Date: Thu, 1 Oct 2009 12:48:38 +0000 (+0000) Subject: 2009-10-01 Ivan Maidanski X-Git-Tag: gc7_2alpha4~71 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=733b99815b7d586d551151934d24551c4c034400;p=gc 2009-10-01 Ivan Maidanski * 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). --- diff --git a/ChangeLog b/ChangeLog index 597cad81..46f2c88f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2009-10-01 Ivan Maidanski + + * 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 * gc_dlopen.c (GC_dlopen): Add function redirector (only if diff --git a/dyn_load.c b/dyn_load.c index 1679ebc2..8539172d 100644 --- a/dyn_load.c +++ b/dyn_load.c @@ -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"); } diff --git a/os_dep.c b/os_dep.c index 0a6b8d8f..6fda51e9 100644 --- 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 +# include 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), \ diff --git a/win32_threads.c b/win32_threads.c index 6bd88936..b12742dd 100644 --- a/win32_threads.c +++ b/win32_threads.c @@ -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