X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=libgc%2Fpthread_stop_world.c;h=3bfdfbf35eddc525cb5667d1e6a258babf555ea5;hb=f3c5893d994437b8a0b0dae8fd6ce6ea847b7389;hp=b1f98099d1e79e60937a2edebd00630d55df6216;hpb=e4d9a7a2e93867ba54b6e88bec915ae2fff1fa94;p=mono.git diff --git a/libgc/pthread_stop_world.c b/libgc/pthread_stop_world.c index b1f98099d1e..3bfdfbf35ed 100644 --- a/libgc/pthread_stop_world.c +++ b/libgc/pthread_stop_world.c @@ -19,18 +19,14 @@ #undef PACKAGE_VERSION #include "mono/utils/mono-compiler.h" -#ifdef MONO_DEBUGGER_SUPPORTED -#include "include/libgc-mono-debugger.h" -#endif - #ifdef NACL -int nacl_park_threads_now = 0; +volatile int __nacl_thread_suspension_needed = 0; pthread_t nacl_thread_parker = -1; -int nacl_thread_parked[MAX_NACL_GC_THREADS]; -int nacl_thread_used[MAX_NACL_GC_THREADS]; -int nacl_thread_parking_inited = 0; -int nacl_num_gc_threads = 0; +volatile int nacl_thread_parked[MAX_NACL_GC_THREADS]; +volatile int nacl_thread_used[MAX_NACL_GC_THREADS]; +volatile int nacl_thread_parking_inited = 0; +volatile int nacl_num_gc_threads = 0; pthread_mutex_t nacl_thread_alloc_lock = PTHREAD_MUTEX_INITIALIZER; __thread int nacl_thread_idx = -1; __thread GC_thread nacl_gc_thread_self = NULL; @@ -290,6 +286,10 @@ static void pthread_push_all_stacks() (unsigned long) lo, (unsigned long) hi); #endif if (0 == lo) ABORT("GC_push_all_stacks: sp not set!\n"); + if (p->altstack && lo >= p->altstack && lo <= p->altstack + p->altstack_size) + hi = p->altstack + p->altstack_size; + /* FIXME: Need to scan the normal stack too, but how ? */ + # ifdef STACK_GROWS_UP /* We got them backwards! */ GC_push_all_stack(hi, lo); @@ -461,15 +461,17 @@ static void pthread_stop_world() #else /* NACL */ GC_thread p; int i; + int num_sleeps = 0; #if DEBUG_THREADS GC_printf1("pthread_stop_world: num_threads %d\n", nacl_num_gc_threads - 1); #endif nacl_thread_parker = pthread_self(); - nacl_park_threads_now = 1; + __nacl_thread_suspension_needed = 1; while (1) { #define NACL_PARK_WAIT_NANOSECONDS 100000 + #define NANOS_PER_SECOND 1000000000 int num_threads_parked = 0; struct timespec ts; int num_used = 0; @@ -491,6 +493,10 @@ static void pthread_stop_world() GC_printf1("sleeping waiting for %d threads to park...\n", nacl_num_gc_threads - num_threads_parked - 1); #endif nanosleep(&ts, 0); + if (++num_sleeps > NANOS_PER_SECOND / NACL_PARK_WAIT_NANOSECONDS) { + GC_printf1("GC appears stalled waiting for %d threads to park...\n", nacl_num_gc_threads - num_threads_parked - 1); + num_sleeps = 0; + } } #endif /* NACL */ @@ -503,31 +509,49 @@ static void pthread_stop_world() #define NACL_STORE_REGS() \ do { \ - asm("push %rbx");\ - asm("push %rbp");\ - asm("push %r12");\ - asm("push %r13");\ - asm("push %r14");\ - asm("push %r15");\ - asm("mov %%esp, %0" : "=m" (nacl_gc_thread_self->stop_info.stack_ptr));\ + __asm__ __volatile__ ("push %rbx");\ + __asm__ __volatile__ ("push %rbp");\ + __asm__ __volatile__ ("push %r12");\ + __asm__ __volatile__ ("push %r13");\ + __asm__ __volatile__ ("push %r14");\ + __asm__ __volatile__ ("push %r15");\ + __asm__ __volatile__ ("mov %%esp, %0" : "=m" (nacl_gc_thread_self->stop_info.stack_ptr));\ memcpy(nacl_gc_thread_self->stop_info.reg_storage, nacl_gc_thread_self->stop_info.stack_ptr, NACL_GC_REG_STORAGE_SIZE * sizeof(ptr_t));\ - asm("add $48, %esp");\ - asm("add %r15, %rsp");\ + __asm__ __volatile__ ("naclasp $48, %r15");\ } while (0) #elif __i386__ #define NACL_STORE_REGS() \ do { \ - asm("push %ebx");\ - asm("push %ebp");\ - asm("push %esi");\ - asm("push %edi");\ - asm("mov %%esp, %0" : "=m" (nacl_gc_thread_self->stop_info.stack_ptr));\ + __asm__ __volatile__ ("push %ebx");\ + __asm__ __volatile__ ("push %ebp");\ + __asm__ __volatile__ ("push %esi");\ + __asm__ __volatile__ ("push %edi");\ + __asm__ __volatile__ ("mov %%esp, %0" : "=m" (nacl_gc_thread_self->stop_info.stack_ptr));\ memcpy(nacl_gc_thread_self->stop_info.reg_storage, nacl_gc_thread_self->stop_info.stack_ptr, NACL_GC_REG_STORAGE_SIZE * sizeof(ptr_t));\ - asm("add $16, %esp");\ + __asm__ __volatile__ ("add $16, %esp");\ } while (0) +#elif __arm__ + +#define NACL_STORE_REGS() \ + do { \ + __asm__ __volatile__ ( \ + ".align 4\n\t" \ + "bic %0, %0, #0xc0000000\n\t" \ + "str sp, [%0]\n\t" \ + "bic %1, %1, #0xc0000000\n\t" \ + "stm %1, {r4-r8,r10-r12,lr}\n\t" \ + : \ + : "r" (&nacl_gc_thread_self->stop_info.stack_ptr), \ + "r"(nacl_gc_thread_self->stop_info.reg_storage) \ + : "memory"); \ + } while (0) +#else + +#error "Please port NACL_STORE_REGS" + #endif void nacl_pre_syscall_hook() @@ -540,6 +564,8 @@ void nacl_pre_syscall_hook() } } +void __nacl_suspend_thread_if_needed(); + void nacl_post_syscall_hook() { /* Calling __nacl_suspend_thread_if_needed() right away should guarantee we don't mutate the GC set. */ @@ -550,7 +576,7 @@ void nacl_post_syscall_hook() } void __nacl_suspend_thread_if_needed() { - if (nacl_park_threads_now) { + if (__nacl_thread_suspension_needed) { pthread_t self = pthread_self(); int local_dummy = 0; /* Don't try to park the thread parker. */ @@ -569,7 +595,7 @@ void __nacl_suspend_thread_if_needed() { nacl_gc_thread_self->stop_info.stack_ptr = (ptr_t)(&local_dummy); } nacl_thread_parked[nacl_thread_idx] = 1; - while (nacl_park_threads_now) + while (__nacl_thread_suspension_needed) ; /* spin */ nacl_thread_parked[nacl_thread_idx] = 0; @@ -585,6 +611,7 @@ void GC_stop_world() { if (GC_notify_event) GC_notify_event (GC_EVENT_PRE_STOP_WORLD); + GC_process_togglerefs (); /* Make sure all free list construction has stopped before we start. */ /* No new construction can start, since free list construction is */ /* required to acquire and release the GC lock before it starts, */ @@ -595,11 +622,6 @@ void GC_stop_world() /* We should have previously waited for it to become zero. */ # endif /* PARALLEL_MARK */ ++GC_stop_count; -#ifdef MONO_DEBUGGER_SUPPORTED - if (gc_thread_vtable && gc_thread_vtable->stop_world) - gc_thread_vtable->stop_world (); - else -#endif pthread_stop_world (); # ifdef PARALLEL_MARK GC_release_mark_lock(); @@ -674,20 +696,19 @@ static void pthread_start_world() GC_printf0("World started\n"); #endif #else /* NACL */ + if (GC_notify_event) + GC_notify_event (GC_EVENT_PRE_START_WORLD); # if DEBUG_THREADS GC_printf0("World starting\n"); # endif - nacl_park_threads_now = 0; + __nacl_thread_suspension_needed = 0; + if (GC_notify_event) + GC_notify_event (GC_EVENT_POST_START_WORLD); #endif /* NACL */ } void GC_start_world() { -#ifdef MONO_DEBUGGER_SUPPORTED - if (gc_thread_vtable && gc_thread_vtable->start_world) - gc_thread_vtable->start_world(); - else -#endif pthread_start_world (); } @@ -739,27 +760,7 @@ static void pthread_stop_init() { /* We hold the allocation lock. */ void GC_stop_init() { -#ifdef MONO_DEBUGGER_SUPPORTED - if (gc_thread_vtable && gc_thread_vtable->initialize) - gc_thread_vtable->initialize (); - else -#endif pthread_stop_init (); } -#ifdef MONO_DEBUGGER_SUPPORTED - -GCThreadFunctions *gc_thread_vtable = NULL; - -void * -GC_mono_debugger_get_stack_ptr (void) -{ - GC_thread me; - - me = GC_lookup_thread (pthread_self ()); - return &me->stop_info.stack_ptr; -} - -#endif - #endif