summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/unistd.h4
-rw-r--r--libc/sysdeps/linux/mips/vfork.S100
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/fork.c23
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/internaltypes.h3
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-vfork.S7
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/pt-fork.c4
6 files changed, 140 insertions, 1 deletions
diff --git a/include/unistd.h b/include/unistd.h
index ab8e4b31a..dfe06c5b2 100644
--- a/include/unistd.h
+++ b/include/unistd.h
@@ -635,7 +635,11 @@ extern int setresgid (__gid_t __egid, __gid_t __rgid, __gid_t __sgid);
/* Clone the calling process, creating an exact copy.
Return -1 for errors, 0 to the new process,
and the process ID of the new process to the old process. */
+#ifdef __PTHREADS_NATIVE__
+extern __pid_t __fork (void) __THROW;
+#else
extern __pid_t fork (void) __THROW;
+#endif
#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED
/* Clone the calling process, but without copying the whole address space.
diff --git a/libc/sysdeps/linux/mips/vfork.S b/libc/sysdeps/linux/mips/vfork.S
new file mode 100644
index 000000000..bdac50b02
--- /dev/null
+++ b/libc/sysdeps/linux/mips/vfork.S
@@ -0,0 +1,100 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/* vfork() is just a special case of clone(). */
+
+#include <sys/asm.h>
+#include <sysdep.h>
+#ifndef __UCLIBC__
+#include <asm/unistd.h>
+#endif
+#include <sgidefs.h>
+
+#ifndef SAVE_PID
+#define SAVE_PID
+#endif
+
+#ifndef RESTORE_PID
+#define RESTORE_PID
+#endif
+
+
+/* int vfork() */
+
+ .text
+LOCALSZ= 1
+FRAMESZ= (((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK
+GPOFF= FRAMESZ-(1*SZREG)
+NESTED(__vfork,FRAMESZ,sp)
+#ifdef __PIC__
+ SETUP_GP
+#endif
+ PTR_SUBU sp, FRAMESZ
+ SETUP_GP64 (a5, __vfork)
+#ifdef __PIC__
+ SAVE_GP (GPOFF)
+#endif
+#ifdef PROF
+# if (_MIPS_SIM != _ABIO32)
+ PTR_S a5, GPOFF(sp)
+# endif
+ .set noat
+ move $1, ra
+# if (_MIPS_SIM == _ABIO32)
+ subu sp,sp,8
+# endif
+ jal _mcount
+ .set at
+# if (_MIPS_SIM != _ABIO32)
+ PTR_L a5, GPOFF(sp)
+# endif
+#endif
+
+ PTR_ADDU sp, FRAMESZ
+
+ SAVE_PID
+
+ li a0, 0x4112 /* CLONE_VM | CLONE_VFORK | SIGCHLD */
+ move a1, sp
+
+ /* Do the system call */
+ li v0,__NR_clone
+ syscall
+
+ RESTORE_PID
+
+ bnez a3,L(error)
+
+ /* Successful return from the parent or child. */
+ RESTORE_GP64
+ ret
+
+ /* Something bad happened -- no child created. */
+L(error):
+#ifdef __PIC__
+ PTR_LA t9, __syscall_error
+ RESTORE_GP64
+ jr t9
+#else
+ RESTORE_GP64
+ j __syscall_error
+#endif
+ END(__vfork)
+
+libc_hidden_def(__vfork)
+weak_alias (__vfork, vfork)
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/fork.c
index 840974401..ea22b0df2 100644
--- a/libpthread/nptl/sysdeps/unix/sysv/linux/fork.c
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/fork.c
@@ -22,7 +22,9 @@
#include <unistd.h>
#include <sys/types.h>
#include <sysdep.h>
+#ifndef __UCLIBC__
#include <libio/libioP.h>
+#endif
#include <tls.h>
#include "fork.h"
#include <hp-timing.h>
@@ -42,10 +44,17 @@ struct fork_handler *__fork_handlers;
static void
fresetlockfiles (void)
{
+#ifdef __UCLIBC__
+ FILE *fp;
+
+ for (fp = _stdio_openlist; fp != NULL; fp = fp->__nextopen)
+ _IO_lock_init(fp->_lock);
+#else
_IO_ITER i;
for (i = _IO_iter_begin(); i != _IO_iter_end(); i = _IO_iter_next(i))
_IO_lock_init (*((_IO_lock_t *) _IO_iter_file(i)->_lock));
+#endif
}
@@ -111,7 +120,11 @@ __libc_fork (void)
break;
}
+#ifdef __UCLIBC__
+ _IO_lock_lock (_stdio_openlist_lock);
+#else
_IO_list_lock ();
+#endif
#ifndef NDEBUG
pid_t ppid = THREAD_GETMEM (THREAD_SELF, tid);
@@ -155,10 +168,16 @@ __libc_fork (void)
fresetlockfiles ();
/* Reset locks in the I/O code. */
+#ifdef __UCLIBC__
+ _IO_lock_init (_stdio_openlist_lock);
+#else
_IO_list_resetlock ();
+#endif
+#ifndef __UCLIBC__
/* Reset the lock the dynamic loader uses to protect its data. */
__rtld_lock_initialize (GL(dl_load_lock));
+#endif
/* Run the handlers registered for the child. */
while (allp != NULL)
@@ -190,7 +209,11 @@ __libc_fork (void)
THREAD_SETMEM (THREAD_SELF, pid, parentpid);
/* We execute this even if the 'fork' call failed. */
+#ifdef __UCLIBC__
+ _IO_lock_unlock(_stdio_openlist_lock);
+#else
_IO_list_unlock ();
+#endif
/* Run the handlers registered for the parent. */
while (allp != NULL)
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/internaltypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/internaltypes.h
index 1dec19e57..7da94d860 100644
--- a/libpthread/nptl/sysdeps/unix/sysv/linux/internaltypes.h
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/internaltypes.h
@@ -21,6 +21,9 @@
#define _INTERNALTYPES_H 1
#include <stdint.h>
+#ifdef __UCLIBC__
+#include <sched.h>
+#endif
struct pthread_attr
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-vfork.S
index fe2b81bc1..f82504329 100644
--- a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-vfork.S
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-vfork.S
@@ -16,6 +16,7 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
+#include <features.h>
#include <tls.h>
/* Save the PID value. */
@@ -34,4 +35,10 @@
sw a2, PID_OFFSET(v1); /* Restore the PID. */ \
1:
+#ifdef __UCLIBC__
+#undef weak_alias
+#define weak_alias(name, aliasname)
+#include <../../../../../../../libc/sysdeps/linux/mips/vfork.S>
+#else
#include <../sysdeps/unix/sysv/linux/mips/vfork.S>
+#endif
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fork.c
index a1e228ee2..8569ef0bf 100644
--- a/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fork.c
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fork.c
@@ -18,7 +18,9 @@
02111-1307 USA. */
#include <unistd.h>
-
+#ifdef __UCLIBC__
+extern pid_t __libc_fork(void);
+#endif
pid_t
__fork (void)