#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;
(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);
pthread_t GC_stopping_thread;
int GC_stopping_pid;
-#ifdef PLATFORM_ANDROID
+#ifdef HOST_ANDROID
static
int android_thread_kill(pid_t tid, int sig)
{
GC_printf1("Sending suspend signal to 0x%lx\n", p -> id);
#endif
-#ifndef PLATFORM_ANDROID
+#ifndef HOST_ANDROID
result = pthread_kill(p -> id, SIG_SUSPEND);
#else
result = android_thread_kill(p -> kernel_id, SIG_SUSPEND);
#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;
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 */
#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()
}
}
+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. */
}
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. */
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;
{
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, */
/* 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();
GC_printf1("Sending restart signal to 0x%lx\n", p -> id);
#endif
-#ifndef PLATFORM_ANDROID
+#ifndef HOST_ANDROID
result = pthread_kill(p -> id, SIG_THR_RESTART);
#else
result = android_thread_kill(p -> kernel_id, SIG_THR_RESTART);
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 ();
}
/* 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