Handle pthread-related changes (mutex/atfork)

First commit:

Revert "Revert "am be741d47: am 2f460fbe: am 73b5cad9: Merge "bionic: Fix wrong kernel_id in pthread descriptor after fork()"""

This reverts commit 06823da2f0c8b4a4ce4c45113032f03df85c94b8.

Second commit:

bionic: fix atfork hanlder_mutex deadlock

This cherry-picks commit 34e89c232dd5645fe3b5f9b40856d8e3e4cae57a

After applying the kernel_id fix, the system refused to boot up and we
got following crash log:
I/DEBUG   (  113): pid: 618, tid: 618  >>> org.simalliance.openmobileapi.service:remote <<<
I/DEBUG   (  113): signal 16 (SIGSTKFLT), code -6 (?), fault addr --------
I/DEBUG   (  113):  eax fffffe00  ebx b77de994  ecx 00000080  edx 00724002
I/DEBUG   (  113):  esi 00000000  edi 00004000
I/DEBUG   (  113):  xcs 00000073  xds 0000007b  xes 0000007b  xfs 00000000 xss 0000007b
I/DEBUG   (  113):  eip b7761351  ebp bfdf3de8  esp bfdf3dc4  flags 00000202
I/DEBUG   (  113):     #00  eip: 00015351  /system/lib/libc.so
I/DEBUG   (  113):     #01  eip: 0000d13c  /system/lib/libc.so (pthread_mutex_lock)
I/DEBUG   (  113):     #02  eip: 00077b48  /system/lib/libc.so (__bionic_atfork_run_prepare)
I/DEBUG   (  113):     #03  eip: 00052cdb  /system/lib/libc.so (fork)
I/DEBUG   (  113):     #04  eip: 0009ae91  /system/lib/libdvm.so (_Z18dvmOptimizeDexFileillPKcjjb)
I/DEBUG   (  113):     #05  eip: 000819d6  /system/lib/libdvm.so (_Z14dvmJarFileOpenPKcS0_PP7JarFileb)
I/DEBUG   (  113):     #06  eip: 000b175e  /system/lib/libdvm.so (_ZL40Dalvik_dalvik_system_DexFile_openDexFilePKjP6JValue)
I/DEBUG   (  113):     #07  eip: 0011fb94  /system/lib/libdvm.so

Root cause:
The atfork uses the mutex handler_mutex to protect the atfork_head. The
parent will call __bionic_atfork_run_prepare() to lock the handler_mutex,
and need both the parent and child to unlock their own copy of handler_mutex
after fork. At that time, the owner of hanlder_mutex is set as the parent.
If we apply the kernel_id fix, then the child's kernel_id will be set as
child's tid.
The handler_mutex is a recursive lock, and pthread_mutex_unlock(&hander_mutex)
will fail because the mutex owner is the parent, while the current tid
(__get_thread()->kernel_id) is child, not matched with the mutex owner.
At that time, the handler_mutex is left in lock state.If the child wants to
fork other process after than, then it will try to lock handler_mutex, and
then be deadlocked.

Fix:
Since the child has its own copy of vm space from the the parent, the
child space's handler_mutex should be reset to the initialized state.

Change-Id: I3907dd9a153418fb78862f2aa6d0302c375d9e27
Signed-off-by: Jack Ren <jack.ren@intel.com>
Signed-off-by: Chenyang Du <chenyang.du@intel.com>
Signed-off-by: Bruce Beare <bruce.j.beare@intel.com>

Change-Id: Ic8072f366a877443a60fe215f3c00b3df5a259c8
diff --git a/libc/bionic/fork.c b/libc/bionic/fork.c
index 0eedb01..2d5a10a 100644
--- a/libc/bionic/fork.c
+++ b/libc/bionic/fork.c
@@ -27,6 +27,7 @@
  */
 #include <unistd.h>
 #include "pthread_internal.h"
+#include "bionic_pthread.h"
 #include "cpuacct.h"
 
 extern int  __fork(void);
@@ -48,6 +49,9 @@
         __timer_table_start_stop(0);
         __bionic_atfork_run_parent();
     } else {
+        /* Adjusting the kernel id after a fork */
+        (void)__pthread_settid(pthread_self(), gettid());
+
         /*
          * Newly created process must update cpu accounting.
          * Call cpuacct_add passing in our uid, which will take
diff --git a/libc/bionic/pthread-atfork.c b/libc/bionic/pthread-atfork.c
index 3a5189d..42420dc 100644
--- a/libc/bionic/pthread-atfork.c
+++ b/libc/bionic/pthread-atfork.c
@@ -74,6 +74,7 @@
 void __bionic_atfork_run_child()
 {
     struct atfork_t *cursor;
+    pthread_mutexattr_t  attr;
 
     /* Call pthread_atfork() child handlers */
     for (cursor = atfork_head.cqh_first;
@@ -84,7 +85,9 @@
         }
     }
 
-    pthread_mutex_unlock(&handler_mutex);
+    pthread_mutexattr_init(&attr);
+    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+    pthread_mutex_init(&handler_mutex, &attr);
 }
 
 void __bionic_atfork_run_parent()
diff --git a/libc/bionic/pthread.c b/libc/bionic/pthread.c
index d9ca432..fdfe508 100644
--- a/libc/bionic/pthread.c
+++ b/libc/bionic/pthread.c
@@ -2292,3 +2292,14 @@
     pthread_internal_t* thread = (pthread_internal_t*)thid;
     return thread->kernel_id;
 }
+
+int __pthread_settid(pthread_t thid, pid_t tid)
+{
+    if (thid == 0)
+        return EINVAL;
+
+    pthread_internal_t* thread = (pthread_internal_t*)thid;
+    thread->kernel_id = tid;
+
+    return 0;
+}
diff --git a/libc/private/bionic_pthread.h b/libc/private/bionic_pthread.h
index 07bcbd4..28d6ad8 100644
--- a/libc/private/bionic_pthread.h
+++ b/libc/private/bionic_pthread.h
@@ -35,6 +35,7 @@
 
 /* Internal, not an NDK API */
 extern pid_t __pthread_gettid(pthread_t thid);
+extern int __pthread_settid(pthread_t thid, pid_t tid);
 
 __END_DECLS