summaryrefslogtreecommitdiff
path: root/libpthread/nptl/sysdeps/unix/sysv/linux/fork.c
diff options
context:
space:
mode:
Diffstat (limited to 'libpthread/nptl/sysdeps/unix/sysv/linux/fork.c')
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/fork.c23
1 files changed, 16 insertions, 7 deletions
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/fork.c
index a84b5c237..2d4cae224 100644
--- a/libpthread/nptl/sysdeps/unix/sysv/linux/fork.c
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/fork.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2007, 2008 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@@ -58,8 +58,9 @@ fresetlockfiles (void)
#endif
}
-extern __typeof(fork) __libc_fork;
-pid_t __libc_fork (void)
+
+pid_t
+__libc_fork (void)
{
pid_t pid;
struct used_handler
@@ -73,6 +74,9 @@ pid_t __libc_fork (void)
struct fork_handler *runp;
while ((runp = __fork_handlers) != NULL)
{
+ /* Make sure we read from the current RUNP pointer. */
+ atomic_full_barrier ();
+
unsigned int oldval = runp->refcntr;
if (oldval == 0)
@@ -166,6 +170,8 @@ pid_t __libc_fork (void)
/* Reset locks in the I/O code. */
STDIO_INIT_MUTEX(_stdio_openlist_add_lock);
+ /* XXX reset any locks in dynamic loader */
+
/* Run the handlers registered for the child. */
while (allp != NULL)
{
@@ -173,8 +179,11 @@ pid_t __libc_fork (void)
allp->handler->child_handler ();
/* Note that we do not have to wake any possible waiter.
- This is the only thread in the new process. */
- --allp->handler->refcntr;
+ This is the only thread in the new process. The count
+ may have been bumped up by other threads doing a fork.
+ We reset it to 1, to avoid waiting for non-existing
+ thread(s) to release the count. */
+ allp->handler->refcntr = 1;
/* XXX We could at this point look through the object pool
and mark all objects not on the __fork_handlers list as
@@ -186,7 +195,7 @@ pid_t __libc_fork (void)
}
/* Initialize the fork lock. */
- __fork_lock = (lll_lock_t) LLL_LOCK_INITIALIZER;
+ __fork_lock = LLL_LOCK_INITIALIZER;
}
else
{
@@ -206,7 +215,7 @@ pid_t __libc_fork (void)
if (atomic_decrement_and_test (&allp->handler->refcntr)
&& allp->handler->need_signal)
- lll_futex_wake (allp->handler->refcntr, 1);
+ lll_futex_wake (allp->handler->refcntr, 1, LLL_PRIVATE);
allp = allp->next;
}