commit 414aff5598a2dea618741bea714fa8dd1baf0d52
Author: Koushik Dutta <koushd@gmail.com>
Date:   Wed Sep 29 21:15:42 2010 -0700

    Work around Android's pthread/kernel_id/fork bug to fix mono multithreading and GC_stop_world in processes that have been forked.

diff --git a/libgc/include/private/pthread_support.h b/libgc/include/private/pthread_support.h
index c2c48c2..ec53e46 100644
--- a/libgc/include/private/pthread_support.h
+++ b/libgc/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/libgc/pthread_stop_world.c b/libgc/pthread_stop_world.c
index 04eb371..603aff7 100644
--- a/libgc/pthread_stop_world.c
+++ b/libgc/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/libgc/pthread_support.c b/libgc/pthread_support.c
index f013204..f70d4f6 100644
--- a/libgc/pthread_support.c
+++ b/libgc/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);
