Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/libgc
diff options
context:
space:
mode:
authorElijah Taylor <elijahtaylor@google.com>2013-02-01 00:04:20 +0400
committerZoltan Varga <vargaz@gmail.com>2013-04-07 11:45:45 +0400
commit1e726ce7a38a92860acab28f4427813d2ba14c13 (patch)
treee832165ae65eab2a49361b4a50509e71214bb4b8 /libgc
parent28c53a39a4630ecb719a94ee6dd6801633799a89 (diff)
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'
Diffstat (limited to 'libgc')
-rw-r--r--libgc/dyn_load.c10
-rw-r--r--libgc/include/private/gcconfig.h59
-rw-r--r--libgc/misc.c12
-rw-r--r--libgc/pthread_stop_world.c12
-rw-r--r--libgc/pthread_support.c24
5 files changed, 74 insertions, 43 deletions
diff --git a/libgc/dyn_load.c b/libgc/dyn_load.c
index e4be3c7d183..ca7ce54f194 100644
--- a/libgc/dyn_load.c
+++ b/libgc/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/libgc/include/private/gcconfig.h b/libgc/include/private/gcconfig.h
index ec53e3a95ea..49ffccddf50 100644
--- a/libgc/include/private/gcconfig.h
+++ b/libgc/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/libgc/misc.c b/libgc/misc.c
index 5b2868d808b..53d47c53dbc 100644
--- a/libgc/misc.c
+++ b/libgc/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/libgc/pthread_stop_world.c b/libgc/pthread_stop_world.c
index 05e897fb739..8b25376b54a 100644
--- a/libgc/pthread_stop_world.c
+++ b/libgc/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/libgc/pthread_support.c b/libgc/pthread_support.c
index 50241e44bf8..b302688a76e 100644
--- a/libgc/pthread_support.c
+++ b/libgc/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 <stdio.h>
+
+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<n>" 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