From a69e9b71b25f739727f126ee33a505495a0ffcaa Mon Sep 17 00:00:00 2001 From: Koushik Dutta Date: Wed, 29 Sep 2010 21:15:42 -0700 Subject: [PATCH] Work around Android's pthread/kernel_id/fork bug to fix mono multithreading and GC_stop_world in processes that have been forked. --- include/private/pthread_support.h | 3 +++ pthread_stop_world.c | 28 ++++++++++++++++++++++++++-- pthread_support.c | 3 +++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/include/private/pthread_support.h b/include/private/pthread_support.h index c2c48c22..ec53e46f 100644 --- a/include/private/pthread_support.h +++ b/include/private/pthread_support.h @@ -26,6 +26,9 @@ typedef struct GC_Thread_Rep { /* 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; diff --git a/pthread_stop_world.c b/pthread_stop_world.c index 04eb3712..603aff78 100644 --- a/pthread_stop_world.c +++ b/pthread_stop_world.c @@ -314,6 +314,22 @@ void GC_push_all_stacks() pthread_t GC_stopping_thread; int GC_stopping_pid; +#ifdef PLATFORM_ANDROID +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 + /* We hold the allocation lock. Suspend all threads that might */ /* still be running. Return the number of suspend signals that */ /* were sent. */ @@ -337,8 +353,12 @@ int GC_suspend_all() #if DEBUG_THREADS GC_printf1("Sending suspend signal to 0x%lx\n", p -> id); #endif - + +#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? */ @@ -465,8 +485,12 @@ static void pthread_start_world() #if DEBUG_THREADS GC_printf1("Sending restart signal to 0x%lx\n", p -> id); #endif - + +#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? */ diff --git a/pthread_support.c b/pthread_support.c index f0132044..f70d4f6e 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -692,6 +692,9 @@ GC_thread GC_new_thread(pthread_t id) } 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); -- 2.40.0