+2010-12-26 Ivan Maidanski <ivmai@mail.ru> (mostly really Geoff Norton
+ and Jonathan Pryor)
+
+ * configure.ac: Use AC_CHECK_LIB() to check for pthread instead of
+ just blindly linking to -lpthread, as Android includes pthread
+ support within libc and does not provide a separate libpthread.
+ * dyn_load.c (GC_register_dynamic_libraries): Skip current link map
+ entry if l_addr is NULL (Android/bionic only).
+ * pthread_stop_world.c (android_thread_kill): New internal function
+ (Android only).
+ * pthread_stop_world.c (GC_suspend_all, GC_start_world): Call
+ android_thread_kill (based on tkill) instead of pthread_kill on
+ Android (since pthread_kill cannot be used safely on the platform).
+ * pthread_support.c (GC_new_thread): Store thread Id (obtained from
+ gettid) for use by android_thread_kill (Android only).
+ * include/private/pthread_support.h (GC_Thread_Rep): Add kernel_id
+ structure member (Android only).
+ * include/private/gcconfig.h: Recognize __x86_64 macro as a synonym
+ of __x86_64__ (Darwin); define __environ macro (Android on M68K).
+ * configure: Regenerate.
+
2010-12-02 Ivan Maidanski <ivmai@mail.ru>
* allchblk.c (GC_freehblk): Print extended error message (done via
#! /bin/sh
-# From configure.ac Revision: 1.62 .
+# From configure.ac Revision: 1.63 .
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.67 for gc 7.2alpha5.
#
;;
posix | pthreads)
THREADS=posix
- THREADDLLIBS=-lpthread
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_self in -lpthread" >&5
+$as_echo_n "checking for pthread_self in -lpthread... " >&6; }
+if test "${ac_cv_lib_pthread_pthread_self+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthread $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_self ();
+int
+main ()
+{
+return pthread_self ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_pthread_pthread_self=yes
+else
+ ac_cv_lib_pthread_pthread_self=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_self" >&5
+$as_echo "$ac_cv_lib_pthread_pthread_self" >&6; }
+if test "x$ac_cv_lib_pthread_pthread_self" = x""yes; then :
+ THREADDLLIBS="-lpthread"
+fi
+
case "$host" in
x86-*-linux* | ia64-*-linux* | i586-*-linux* | i686-*-linux* | x86_64-*-linux* | alpha-*-linux* | sparc*-*-linux*)
$as_echo "#define GC_LINUX_THREADS 1" >>confdefs.h
AC_CONFIG_MACRO_DIR([m4])
AC_CANONICAL_TARGET
AC_PREREQ(2.53)
-AC_REVISION($Revision: 1.63 $)
+AC_REVISION($Revision: 1.64 $)
GC_SET_VERSION
AM_INIT_AUTOMAKE([foreign dist-bzip2 nostdinc])
AM_CONFIG_HEADER([include/private/config.h])
;;
posix | pthreads)
THREADS=posix
- THREADDLLIBS=-lpthread
+ AC_CHECK_LIB(pthread, pthread_self, THREADDLLIBS="-lpthread",,)
case "$host" in
x86-*-linux* | ia64-*-linux* | i586-*-linux* | i686-*-linux* | x86_64-*-linux* | alpha-*-linux* | sparc*-*-linux*)
AC_DEFINE(GC_LINUX_THREADS)
int i;
e = (ElfW(Ehdr) *) lm->l_addr;
+# ifdef PLATFORM_ANDROID
+ if (e == NULL)
+ continue;
+# endif
p = ((ElfW(Phdr) *)(((char *)(e)) + e->e_phoff));
offset = ((unsigned long)(lm->l_addr));
for( i = 0; i < (int)(e->e_phnum); ((i++),(p++)) ) {
int i;
e = (ElfW(Ehdr) *) lm->l_addr;
+# ifdef PLATFORM_ANDROID
+ if (e == NULL)
+ continue;
+# endif
p = ((ElfW(Phdr) *)(((char *)(e)) + e->e_phoff));
offset = ((unsigned long)(lm->l_addr));
for( i = 0; i < (int)(e->e_phnum); ((i++),(p++)) ) {
# if defined(__ppc__) || defined(__ppc64__)
# define POWERPC
# define mach_type_known
-# elif defined(__x86_64__)
+# elif defined(__x86_64__) || defined(__x86_64)
# define X86_64
# define mach_type_known
# elif defined(__i386__)
# if defined(__GLIBC__)&& __GLIBC__>=2
# define SEARCH_FOR_DATA_START
# else /* !GLIBC2 */
+# ifdef PLATFORM_ANDROID
+# define __environ environ
+# endif
extern char **__environ;
# define DATASTART ((ptr_t)(&__environ))
/* hideous kludge: __environ is the first */
# define GETPAGESIZE() getpagesize()
/* There seems to be some issues with trylock hanging on darwin. This
should be looked into some more */
-# define NO_PTHREAD_TRYLOCK
+# define NO_PTHREAD_TRYLOCK
# endif /* DARWIN */
# endif
/* guaranteed to be dead, but we may */
/* not yet have registered the join.) */
pthread_t id;
+# ifdef PLATFORM_ANDROID
+ pid_t kernel_id;
+# endif
/* Extra bookkeeping information the stopping code uses */
struct thread_stop_info stop_info;
int GC_stopping_pid = 0;
#endif
+#ifdef PLATFORM_ANDROID
+ static int android_thread_kill(pid_t tid, int sig)
+ {
+ int ret;
+ int old_errno = errno;
+
+ ret = tkill(tid, sig);
+ if (ret < 0) {
+ ret = errno;
+ errno = old_errno;
+ }
+
+ return ret;
+ }
+#endif /* PLATFORM_ANDROID */
+
/* We hold the allocation lock. Suspend all threads that might */
/* still be running. Return the number of suspend signals that */
/* were sent. */
p -> stop_info.stack_ptr =
*(ptr_t *)((char *)p -> id + UTHREAD_SP_OFFSET);
# else
- result = pthread_kill(p -> id, SIG_SUSPEND);
+# ifndef PLATFORM_ANDROID
+ result = pthread_kill(p -> id, SIG_SUSPEND);
+# else
+ result = android_thread_kill(p -> kernel_id, SIG_SUSPEND);
+# endif
switch(result) {
case ESRCH:
/* Not really there anymore. Possible? */
# ifdef GC_OPENBSD_THREADS
if (pthread_resume_np(p -> id) != 0)
- ABORT("pthread_kill failed");
+ ABORT("pthread_resume_np failed");
# else
- result = pthread_kill(p -> id, SIG_THR_RESTART);
+# ifndef PLATFORM_ANDROID
+ result = pthread_kill(p -> id, SIG_THR_RESTART);
+# else
+ result = android_thread_kill(p -> kernel_id, SIG_THR_RESTART);
+# endif
switch(result) {
case ESRCH:
/* Not really there anymore. Possible? */
if (result == 0) return(0);
}
result -> id = id;
+# ifdef PLATFORM_ANDROID
+ result -> kernel_id = gettid();
+# endif
result -> next = GC_threads[hv];
GC_threads[hv] = result;
GC_ASSERT(result -> flags == 0 && result -> thread_blocked == 0);