From: hboehm Date: Sat, 28 Feb 2009 23:29:44 +0000 (+0000) Subject: 2009-02-28 Hans Boehm (With input from Ivan Maidansky) X-Git-Tag: gc7_2alpha2~37 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6aed8bc60c99a11ab94c8dca3b7ca15926f10c4b;p=gc 2009-02-28 Hans Boehm (With input from Ivan Maidansky) * win32_threads.c (GC_push_stack_for): Yet another attempt at the stack_min finding logic. Try to clean up the existing code while minimizing VirtualQuery calls. (GC_win32_start_inner): Register thread before GC_printf. Produce more output with DEBUG_THREADS. *include/gc.h: Update obsolete comments. --- diff --git a/ChangeLog b/ChangeLog index 7547a662..6684b574 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2009-02-28 Hans Boehm (With input from Ivan Maidansky) + * win32_threads.c (GC_push_stack_for): Yet another attempt + at the stack_min finding logic. Try to clean up the existing code + while minimizing VirtualQuery calls. + (GC_win32_start_inner): Register thread before GC_printf. + Produce more output with DEBUG_THREADS. + *include/gc.h: Update obsolete comments. + 2009-02-24 Hans Boehm (Really Ivan Maidansky) * tests/test.c: (gcj_class_struct2): Use cast instead of l suffix. diff --git a/include/gc.h b/include/gc.h index 335dd09a..ba4ca32c 100644 --- a/include/gc.h +++ b/include/gc.h @@ -56,9 +56,6 @@ typedef unsigned long GC_word; typedef long GC_signed_word; #else - /* Win64 isn't really supported yet, but this is the first step. And */ - /* it might cause error messages to show up in more plausible places. */ - /* This needs basetsd.h, which is included by windows.h. */ #ifdef __int64 typedef unsigned __int64 GC_word; typedef __int64 GC_signed_word; @@ -274,9 +271,8 @@ GC_API void GC_CALL GC_init(void); * be reachable. GC_malloc_uncollectable and GC_free called on the resulting * object implicitly update GC_non_gc_bytes appropriately. * - * Note that the GC_malloc_stubborn support is stubbed out by default - * starting in 6.0. GC_malloc_stubborn is an alias for GC_malloc unless - * the collector is built with STUBBORN_ALLOC defined. + * Note that the GC_malloc_stubborn support doesn't really + * exist anymore. MANUAL_VDB provides comparable functionality. */ GC_API void * GC_CALL GC_malloc(size_t size_in_bytes); GC_API void * GC_CALL GC_malloc_atomic(size_t size_in_bytes); diff --git a/win32_threads.c b/win32_threads.c index 2c56ffd2..19318144 100644 --- a/win32_threads.c +++ b/win32_threads.c @@ -944,36 +944,53 @@ STATIC void GC_push_stack_for(GC_thread thread) # endif } /* ! current thread */ - /* If got sp value seems to be correct (at least, less than the */ - /* bottom of the stack) then do its further validation by quick */ - /* probing the memory region at it. */ /* Set stack_min to the lowest address in the thread stack, */ + /* or to an address in the thread stack no larger than sp, */ /* 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(thread -> stack_base); + thread -> last_stack_min = stack_min; } else { -# ifdef MSWINCE - stack_min = GC_get_stack_min(thread -> stack_base); -# else - if (GC_may_be_in_stack(thread -> last_stack_min)) { - stack_min = GC_get_stack_min(thread -> last_stack_min); - } else { + if (sp < thread -> stack_base && sp >= thread -> last_stack_min) { + stack_min = sp; + } else { +# ifdef MSWINCE stack_min = GC_get_stack_min(thread -> stack_base); - } -# endif +# else + if (GC_may_be_in_stack(thread -> last_stack_min)) { + 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 + thread -> last_stack_min = stack_min; + } } - thread -> last_stack_min = stack_min; + GC_ASSERT(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)); if (sp >= stack_min && sp < thread->stack_base) { # ifdef DEBUG_THREADS - GC_printf("Pushing thread from %p to %p for 0x%x from 0x%x\n", - sp, thread -> stack_base, (int)thread -> id, (int)me); + GC_printf("Pushing stack for 0x%x from sp %p to %p from 0x%x\n", + (int)thread -> id, sp, thread -> stack_base, (int)me); # endif GC_push_all_stack(sp, thread->stack_base); } else { - WARN("Thread stack pointer 0x%lx out of range, pushing everything\n", - (unsigned long)(size_t)sp); + /* If not current thread then it is possible for sp to point to */ + /* the guarded (untouched yet) page just below the current */ + /* stack_min of the thread. */ + if (thread -> id == me || sp >= thread->stack_base + || sp + GC_page_size < stack_min) + WARN("Thread stack pointer 0x%lx out of range, pushing everything\n", + (unsigned long)(size_t)sp); +# ifdef DEBUG_THREADS + GC_printf("Pushing stack for 0x%x from (min) %p to %p from 0x%x\n", + (int)thread -> id, stack_min, + thread -> stack_base, (int)me); +# endif GC_push_all_stack(stack_min, thread->stack_base); } } /* thread looks live */ @@ -1470,12 +1487,12 @@ STATIC void * GC_CALLBACK GC_win32_start_inner(struct GC_stack_base *sb, void * ret; thread_args *args = (thread_args *)arg; + GC_register_my_thread(sb); /* This waits for an in-progress GC. */ + # if DEBUG_WIN32_THREADS GC_printf("thread 0x%x starting...\n", (unsigned)GetCurrentThreadId()); # endif - GC_register_my_thread(sb); /* This waits for an in-progress GC. */ - /* Clear the thread entry even if we exit with an exception. */ /* This is probably pointless, since an uncaught exception is */ /* supposed to result in the process being killed. */ @@ -2128,6 +2145,9 @@ void GC_mark_thread_local_free_lists(void) for (i = 0; i < THREAD_TABLE_SZ; ++i) { for (p = GC_threads[i]; 0 != p; p = p -> next) { +# ifdef DEBUG_THREADS + GC_printf("Marking thread locals for 0x%x\n", p -> id); +# endif GC_mark_thread_local_fls_for(&(p->tlfs)); } }