summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Fischer <matt.fischer@garmin.com>2010-06-25 14:36:39 -0500
committerJean-Baptiste Queru <jbq@google.com>2010-07-23 13:10:16 -0700
commit4f086aeb4aa06e13079b7fec71a8178ceeacf318 (patch)
treea6b0fbce5c6d0f507a244ef4f87ec648b7c35a76
parente73a571fd9b60315681eacbef5857f0f0b1ece18 (diff)
downloadbionic-android-sdk-tools_r7.zip
bionic-android-sdk-tools_r7.tar.gz
bionic-android-sdk-tools_r7.tar.bz2
Implemented pthread_atfork()android-sdk-tools_r7android-adt-0.9.8
Change-Id: Ie6c0bf593315d3507b3c4a6c8903a74a1fa053db
-rw-r--r--libc/Android.mk3
-rw-r--r--libc/bionic/fork.c4
-rw-r--r--libc/bionic/pthread-atfork.c123
-rw-r--r--libc/bionic/pthread_internal.h3
-rw-r--r--libc/docs/CHANGES.TXT8
-rw-r--r--libc/include/pthread.h2
6 files changed, 142 insertions, 1 deletions
diff --git a/libc/Android.mk b/libc/Android.mk
index 7a7d9e3..568cc94 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -324,6 +324,7 @@ libc_common_src_files += \
# up any thumb code.
libc_common_src_files += \
bionic/pthread.c.arm \
+ bionic/pthread-atfork.c.arm \
bionic/pthread-timers.c.arm \
bionic/ptrace.c.arm
@@ -358,6 +359,7 @@ libc_common_src_files += \
arch-x86/string/strncmp_wrapper.S \
arch-x86/string/strlen.S \
bionic/pthread.c \
+ bionic/pthread-atfork.c \
bionic/pthread-timers.c \
bionic/ptrace.c
@@ -394,6 +396,7 @@ libc_common_src_files += \
string/memcmp.c \
string/strlen.c \
bionic/pthread.c \
+ bionic/pthread-atfork.c \
bionic/pthread-timers.c \
bionic/ptrace.c \
unistd/socketcalls.c
diff --git a/libc/bionic/fork.c b/libc/bionic/fork.c
index e20f548..8d3ea4b 100644
--- a/libc/bionic/fork.c
+++ b/libc/bionic/fork.c
@@ -40,9 +40,12 @@ int fork(void)
* of error, or in the parent process
*/
__timer_table_start_stop(1);
+ __bionic_atfork_run_prepare();
+
ret = __fork();
if (ret != 0) { /* not a child process */
__timer_table_start_stop(0);
+ __bionic_atfork_run_parent();
} else {
/*
* Newly created process must update cpu accounting.
@@ -51,6 +54,7 @@ int fork(void)
* as a parameter.
*/
cpuacct_add(getuid());
+ __bionic_atfork_run_child();
}
return ret;
}
diff --git a/libc/bionic/pthread-atfork.c b/libc/bionic/pthread-atfork.c
new file mode 100644
index 0000000..3a5189d
--- /dev/null
+++ b/libc/bionic/pthread-atfork.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <stdlib.h>
+#include <errno.h>
+#include <pthread.h>
+#include <sys/queue.h>
+
+static pthread_mutex_t handler_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
+
+struct atfork_t
+{
+ CIRCLEQ_ENTRY(atfork_t) entries;
+
+ void (*prepare)(void);
+ void (*child)(void);
+ void (*parent)(void);
+};
+static CIRCLEQ_HEAD(atfork_head_t, atfork_t) atfork_head = \
+ CIRCLEQ_HEAD_INITIALIZER(atfork_head);
+
+void __bionic_atfork_run_prepare()
+{
+ struct atfork_t *cursor;
+
+ /* We will lock this here, and unlock it in the parent and child functions.
+ * This ensures that nobody can modify the handler array between the calls
+ * to the prepare and parent/child handlers.
+ *
+ * TODO: If a handler mucks with the list, it could cause problems. Right
+ * now it's ok because all they can do is add new items to the end
+ * of the list, but if/when we implement cleanup in dlclose() things
+ * will get more interesting...
+ */
+ pthread_mutex_lock(&handler_mutex);
+
+ /* Call pthread_atfork() prepare handlers. Posix states that the prepare
+ * handlers should be called in the reverse order of the parent/child
+ * handlers, so we iterate backwards.
+ */
+ for (cursor = atfork_head.cqh_last;
+ cursor != (void*)&atfork_head;
+ cursor = cursor->entries.cqe_prev) {
+ if (cursor->prepare != NULL) {
+ cursor->prepare();
+ }
+ }
+}
+
+void __bionic_atfork_run_child()
+{
+ struct atfork_t *cursor;
+
+ /* Call pthread_atfork() child handlers */
+ for (cursor = atfork_head.cqh_first;
+ cursor != (void*)&atfork_head;
+ cursor = cursor->entries.cqe_next) {
+ if (cursor->child != NULL) {
+ cursor->child();
+ }
+ }
+
+ pthread_mutex_unlock(&handler_mutex);
+}
+
+void __bionic_atfork_run_parent()
+{
+ struct atfork_t *cursor;
+
+ /* Call pthread_atfork() parent handlers */
+ for (cursor = atfork_head.cqh_first;
+ cursor != (void*)&atfork_head;
+ cursor = cursor->entries.cqe_next) {
+ if (cursor->parent != NULL) {
+ cursor->parent();
+ }
+ }
+
+ pthread_mutex_unlock(&handler_mutex);
+}
+
+int pthread_atfork(void (*prepare)(void), void (*parent)(void), void(*child)(void))
+{
+ struct atfork_t *entry = malloc(sizeof(struct atfork_t));
+
+ if (entry == NULL) {
+ return ENOMEM;
+ }
+
+ entry->prepare = prepare;
+ entry->parent = parent;
+ entry->child = child;
+
+ pthread_mutex_lock(&handler_mutex);
+ CIRCLEQ_INSERT_TAIL(&atfork_head, entry, entries);
+ pthread_mutex_unlock(&handler_mutex);
+
+ return 0;
+}
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
index eb4e80c..655b8f3 100644
--- a/libc/bionic/pthread_internal.h
+++ b/libc/bionic/pthread_internal.h
@@ -109,6 +109,9 @@ extern int __pthread_cond_timedwait_relative(pthread_cond_t*,
/* needed by fork.c */
extern void __timer_table_start_stop(int stop);
+extern void __bionic_atfork_run_prepare();
+extern void __bionic_atfork_run_child();
+extern void __bionic_atfork_run_parent();
__END_DECLS
diff --git a/libc/docs/CHANGES.TXT b/libc/docs/CHANGES.TXT
index 9080685..b0725ed 100644
--- a/libc/docs/CHANGES.TXT
+++ b/libc/docs/CHANGES.TXT
@@ -1,7 +1,13 @@
Bionic ChangeLog:
-----------------
-Differences between current and Android 2.1:
+Differences between current and Android 2.2:
+
+- Added an implementation of pthread_atfork()
+
+
+-------------------------------------------------------------------------------
+Differences between Android 2.2 and Android 2.1:
- Add support for SH-4 CPU architecture !
diff --git a/libc/include/pthread.h b/libc/include/pthread.h
index 944bb68..ecabdb1 100644
--- a/libc/include/pthread.h
+++ b/libc/include/pthread.h
@@ -233,6 +233,8 @@ int pthread_once(pthread_once_t *once_control, void (*init_routine)(void));
int pthread_setname_np(pthread_t thid, const char *thname);
+int pthread_atfork(void (*prepare)(void), void (*parent)(void), void(*child)(void));
+
typedef void (*__pthread_cleanup_func_t)(void*);
typedef struct __pthread_cleanup_t {