From b328e8824e6ffa7cbd38c83e26433bee24bd3bb1 Mon Sep 17 00:00:00 2001 From: Elijah Taylor Date: Thu, 31 Jan 2013 12:04:20 -0800 Subject: [PATCH] NaCl runtime fixes - fix compile/runtime issues caused by upstream changes - add NaCl glibc support - various changes to support running tests in NaCl glibc from 'make check' --- dyn_load.c | 10 +++---- include/private/gcconfig.h | 59 +++++++++++++++++++------------------- misc.c | 12 ++++++++ pthread_stop_world.c | 12 ++++---- pthread_support.c | 24 +++++++++++++--- 5 files changed, 74 insertions(+), 43 deletions(-) diff --git a/dyn_load.c b/dyn_load.c index e4be3c7d..ca7ce54f 100644 --- a/dyn_load.c +++ b/dyn_load.c @@ -26,7 +26,7 @@ * None of this is safe with dlclose and incremental collection. * But then not much of anything is safe in the presence of dlclose. */ -#if defined(__linux__) && !defined(_GNU_SOURCE) +#if (defined(__linux__) || defined(__native_client__)) && !defined(_GNU_SOURCE) /* Can't test LINUX, since this must be define before other includes */ # define _GNU_SOURCE #endif @@ -54,7 +54,7 @@ #if !defined(SUNOS4) && !defined(SUNOS5DL) && !defined(IRIX5) && \ !defined(MSWIN32) && !defined(MSWINCE) && \ !(defined(ALPHA) && defined(OSF1)) && \ - !defined(HPUX) && !(defined(LINUX) && defined(__ELF__)) && \ + !defined(HPUX) && !((defined(LINUX) || defined(NACL)) && defined(__ELF__)) && \ !defined(RS6000) && !defined(SCO_ELF) && !defined(DGUX) && \ !(defined(FREEBSD) && defined(__ELF__)) && \ !(defined(OPENBSD) && (defined(__ELF__) || defined(M68K))) && \ @@ -91,7 +91,7 @@ # define ELFSIZE ARCH_ELFSIZE #endif -#if defined(LINUX) && defined(__ELF__) || defined(SCO_ELF) || \ +#if (defined(LINUX) || defined(NACL)) && defined(__ELF__) || defined(SCO_ELF) || \ (defined(FREEBSD) && defined(__ELF__)) || defined(DGUX) || \ (defined(OPENBSD) && defined(__ELF__)) || \ (defined(NETBSD) && defined(__ELF__)) || defined(HURD) @@ -297,7 +297,7 @@ void GC_register_dynamic_libraries() # endif /* !USE_PROC ... */ # endif /* SUNOS */ -#if defined(LINUX) && defined(__ELF__) || defined(SCO_ELF) || \ +#if (defined(LINUX) || defined(NACL)) && defined(__ELF__) || defined(SCO_ELF) || \ (defined(FREEBSD) && defined(__ELF__)) || defined(DGUX) || \ (defined(OPENBSD) && defined(__ELF__)) || \ (defined(NETBSD) && defined(__ELF__)) || defined(HURD) @@ -394,7 +394,7 @@ GC_bool GC_register_main_static_data() /* For glibc 2.2.4+. Unfortunately, it doesn't work for older */ /* versions. Thanks to Jakub Jelinek for most of the code. */ -# if defined(LINUX) /* Are others OK here, too? */ \ +# if (defined(LINUX) || defined(NACL)) /* Are others OK here, too? */ \ && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) \ || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && defined(DT_CONFIG))) diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h index ec53e3a9..49ffccdd 100644 --- a/include/private/gcconfig.h +++ b/include/private/gcconfig.h @@ -67,8 +67,12 @@ /* Determine the machine type: */ # if defined(__native_client__) # define NACL -# define I386 -# define mach_type_known +# if !defined(__portable_native_client__) +# define I386 +# define mach_type_known +# else + /* Here we will rely upon arch-specific defines. */ +# endif # endif # if defined(__arm__) || defined(__thumb__) # define ARM32 @@ -928,6 +932,30 @@ # endif # endif + +# ifdef NACL +# define OS_TYPE "NACL" +# if defined(__GLIBC__) +# define DYNAMIC_LOADING +# endif +# define DATASTART ((ptr_t)0x10020000) + extern int _end[]; +# define DATAEND (_end) +# ifdef STACK_GRAN +# undef STACK_GRAN +# endif /* STACK_GRAN */ +# define STACK_GRAN 0x10000 +# define HEURISTIC1 +# define USE_MMAP +# define USE_MUNMAP +# define USE_MMAP_ANON +# ifdef USE_MMAP_FIXED +# undef USE_MMAP_FIXED +# endif +# define GETPAGESIZE() 65536 +# define MAX_NACL_GC_THREADS 1024 +# endif + # ifdef VAX # define MACH_TYPE "VAX" # define ALIGNMENT 4 /* Pointers are longword aligned by 4.2 C compiler */ @@ -1204,33 +1232,6 @@ # define HEAP_START DATAEND # endif /* USE_MMAP */ # endif /* DGUX */ -# ifdef NACL -# define OS_TYPE "NACL" - extern int etext[]; -//# define DATASTART ((ptr_t)((((word) (etext)) + 0xfff) & ~0xfff)) -# define DATASTART ((ptr_t)0x10000000) - extern int _end[]; -# define DATAEND (_end) -# ifdef STACK_GRAN -# undef STACK_GRAN -# endif /* STACK_GRAN */ -# define STACK_GRAN 0x10000 -# define HEURISTIC1 -# ifdef USE_MMAP -# undef USE_MMAP -# endif -# ifdef USE_MUNMAP -# undef USE_MUNMAP -# endif -# ifdef USE_MMAP_ANON -# undef USE_MMAP_ANON -# endif -# ifdef USE_MMAP_FIXED -# undef USE_MMAP_FIXED -# endif -# define GETPAGESIZE() 65536 -# define MAX_NACL_GC_THREADS 1024 -# endif # ifdef LINUX # ifndef __GNUC__ /* The Intel compiler doesn't like inline assembly */ diff --git a/misc.c b/misc.c index 5b2868d8..53d47c53 100644 --- a/misc.c +++ b/misc.c @@ -1003,7 +1003,11 @@ long a, b, c, d, e, f; buf[1024] = 0x15; (void) sprintf(buf, format, a, b, c, d, e, f); if (buf[1024] != 0x15) ABORT("GC_printf clobbered stack"); +#ifdef NACL + WRITE(GC_stdout, buf, strlen(buf)); +#else if (WRITE(GC_stdout, buf, strlen(buf)) < 0) ABORT("write to stdout failed"); +#endif } void GC_err_printf(format, a, b, c, d, e, f) @@ -1015,13 +1019,21 @@ long a, b, c, d, e, f; buf[1024] = 0x15; (void) sprintf(buf, format, a, b, c, d, e, f); if (buf[1024] != 0x15) ABORT("GC_err_printf clobbered stack"); +#ifdef NACL + WRITE(GC_stderr, buf, strlen(buf)); +#else if (WRITE(GC_stderr, buf, strlen(buf)) < 0) ABORT("write to stderr failed"); +#endif } void GC_err_puts(s) GC_CONST char *s; { +#ifdef NACL + WRITE(GC_stderr, s, strlen(s)); +#else if (WRITE(GC_stderr, s, strlen(s)) < 0) ABORT("write to stderr failed"); +#endif } #if defined(LINUX) && !defined(SMALL_CONFIG) diff --git a/pthread_stop_world.c b/pthread_stop_world.c index 05e897fb..8b25376b 100644 --- a/pthread_stop_world.c +++ b/pthread_stop_world.c @@ -24,7 +24,7 @@ #endif #ifdef NACL -int nacl_park_threads_now = 0; +volatile int __nacl_thread_suspension_needed = 0; pthread_t nacl_thread_parker = -1; volatile int nacl_thread_parked[MAX_NACL_GC_THREADS]; @@ -471,7 +471,7 @@ static void pthread_stop_world() 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 @@ -549,6 +549,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. */ @@ -559,7 +561,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. */ @@ -578,7 +580,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; @@ -688,7 +690,7 @@ static void pthread_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 */ diff --git a/pthread_support.c b/pthread_support.c index 50241e44..b302688a 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -699,10 +699,20 @@ extern void nacl_pre_syscall_hook(); extern void nacl_post_syscall_hook(); extern void nacl_register_gc_hooks(void (*pre)(), void (*post)()); +#include + +struct nacl_irt_blockhook { + int (*register_block_hooks)(void (*pre)(void), void (*post)(void)); +}; + +extern size_t nacl_interface_query(const char *interface_ident, + void *table, size_t tablesize); + void nacl_initialize_gc_thread() { int i; - nacl_register_gc_hooks(nacl_pre_syscall_hook, nacl_post_syscall_hook); + static struct nacl_irt_blockhook gc_hook; + pthread_mutex_lock(&nacl_thread_alloc_lock); if (!nacl_thread_parking_inited) { @@ -710,6 +720,10 @@ void nacl_initialize_gc_thread() nacl_thread_used[i] = 0; nacl_thread_parked[i] = 0; } + // TODO: replace with public 'register hook' function when + // available from glibc + nacl_interface_query("nacl-irt-blockhook-0.1", &gc_hook, sizeof(gc_hook)); + gc_hook.register_block_hooks(nacl_pre_syscall_hook, nacl_post_syscall_hook); nacl_thread_parking_inited = 1; } GC_ASSERT(nacl_num_gc_threads <= MAX_NACL_GC_THREADS); @@ -942,6 +956,7 @@ int GC_segment_is_thread_stack(ptr_t lo, ptr_t hi) /* Return the number of processors, or i<= 0 if it can't be determined. */ int GC_get_nprocs() { +#ifndef NACL /* Should be "return sysconf(_SC_NPROCESSORS_ONLN);" but that */ /* appears to be buggy in many cases. */ /* We look for lines "cpu" in /proc/stat. */ @@ -971,6 +986,9 @@ int GC_get_nprocs() } close(f); return result; +#else /* NACL */ + return sysconf(_SC_NPROCESSORS_ONLN); +#endif } #endif /* GC_LINUX_THREADS */ @@ -1362,12 +1380,10 @@ int WRAP_FUNC(pthread_join)(pthread_t thread, void **retval) } #ifdef NACL -/* Native Client doesn't support pthread cleanup functions, */ -/* so wrap pthread_exit and manually cleanup the thread. */ +/* TODO: remove, NaCl glibc now supports pthread cleanup functions. */ void WRAP_FUNC(pthread_exit)(void *status) { - GC_thread_exit_proc(0); REAL_FUNC(pthread_exit)(status); } #endif -- 2.40.0