summaryrefslogtreecommitdiffstats
path: root/lib/libthr/thread/thr_syscalls.c
diff options
context:
space:
mode:
authormtm <mtm@FreeBSD.org>2004-06-27 10:01:35 +0000
committermtm <mtm@FreeBSD.org>2004-06-27 10:01:35 +0000
commit32356d604915fd82194fe6d674571b7db002f1b7 (patch)
tree7f18580f62576acd89a952ab6952543489b92ea1 /lib/libthr/thread/thr_syscalls.c
parent7598f9b9ec4cee0a912b90d99abf745006764240 (diff)
downloadFreeBSD-src-32356d604915fd82194fe6d674571b7db002f1b7.zip
FreeBSD-src-32356d604915fd82194fe6d674571b7db002f1b7.tar.gz
Implement pthread_atfork in libthr. This is mostly from deichen's
work in libpthread. Submitted by: Dan Nelson <dnelson@allantgroup.com>
Diffstat (limited to 'lib/libthr/thread/thr_syscalls.c')
-rw-r--r--lib/libthr/thread/thr_syscalls.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/lib/libthr/thread/thr_syscalls.c b/lib/libthr/thread/thr_syscalls.c
index f0867d1..b899cbf 100644
--- a/lib/libthr/thread/thr_syscalls.c
+++ b/lib/libthr/thread/thr_syscalls.c
@@ -90,6 +90,8 @@
#include "thr_private.h"
+extern spinlock_t *__malloc_lock;
+
extern int __creat(const char *, mode_t);
extern int __sleep(unsigned int);
extern int __sys_nanosleep(const struct timespec *, struct timespec *);
@@ -174,6 +176,62 @@ _fcntl(int fd, int cmd,...)
return ret;
}
+__weak_reference(_fork, fork);
+
+int
+_fork(int fd)
+{
+ int ret;
+ struct pthread_atfork *af;
+
+ _pthread_mutex_lock(&_atfork_mutex);
+
+ /* Run down atfork prepare handlers. */
+ TAILQ_FOREACH_REVERSE(af, &_atfork_list, atfork_head, qe) {
+ if (af->prepare != NULL)
+ af->prepare();
+ }
+
+ /*
+ * Fork a new process.
+ * XXX - The correct way to handle __malloc_lock is to have
+ * the threads libraries (or libc) install fork handlers for it
+ * in their initialization routine. We should probably
+ * do that for all the locks in libc.
+ */
+ if (__isthreaded && __malloc_lock != NULL)
+ _SPINLOCK(__malloc_lock);
+ ret = __sys_fork();
+ if (ret == 0) {
+ __isthreaded = 0;
+ if (__malloc_lock != NULL)
+ memset(__malloc_lock, 0, sizeof(spinlock_t));
+ init_tdlist(curthread, 1);
+ init_td_common(curthread, NULL, 1);
+ _mutex_reinit(&_atfork_mutex);
+
+ /* Run down atfork child handlers. */
+ TAILQ_FOREACH(af, &_atfork_list, qe) {
+ if (af->child != NULL)
+ af->child();
+ }
+ } else if (ret != -1) {
+ /* Run down atfork parent handlers. */
+ TAILQ_FOREACH(af, &_atfork_list, qe) {
+ if (af->parent != NULL)
+ af->parent();
+ }
+ }
+
+ if (ret != 0) {
+ if (__isthreaded && __malloc_lock != NULL)
+ _SPINUNLOCK(__malloc_lock);
+ _pthread_mutex_unlock(&_atfork_mutex);
+ }
+ return ret;
+}
+
+
__weak_reference(_fsync, fsync);
int
OpenPOWER on IntegriCloud