+#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_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;
+ /* Check the 'parked' flag for each thread the GC knows about */
+ for (i = 0; i < MAX_NACL_GC_THREADS && num_used < nacl_num_gc_threads; i++) {
+ if (nacl_thread_used[i] == 1) {
+ num_used++;
+ if (nacl_thread_parked[i] == 1) {
+ num_threads_parked++;
+ }
+ }
+ }
+ /* -1 for the current thread */
+ if (num_threads_parked >= nacl_num_gc_threads - 1)
+ break;
+ ts.tv_sec = 0;
+ ts.tv_nsec = NACL_PARK_WAIT_NANOSECONDS;
+ #if DEBUG_THREADS
+ 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 */
+}
+
+
+#ifdef NACL
+
+#if __x86_64__
+
+#define NACL_STORE_REGS() \
+ do { \
+ __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__ __volatile__ ("naclasp $48, %r15");\
+ } while (0)
+
+#elif __i386__
+
+#define NACL_STORE_REGS() \
+ do { \
+ __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__ __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()
+{
+ int local_dummy = 0;
+ if (nacl_thread_idx != -1) {
+ NACL_STORE_REGS();
+ nacl_gc_thread_self->stop_info.stack_ptr = (ptr_t)(&local_dummy);
+ nacl_thread_parked[nacl_thread_idx] = 1;
+ }