[git commit master] nptl: mips needs updated clone() implementation

Austin Foxley austinf at cetoncorp.com
Tue Apr 27 15:43:43 UTC 2010


commit: http://git.uclibc.org/uClibc/commit/?id=c06dab26652af40a8780790e48bcef1c64aaeb83
branch: http://git.uclibc.org/uClibc/commit/?id=refs/heads/master

Signed-off-by: Andreas Schultz <andreas.schultz at gmail.com>
Signed-off-by: Austin Foxley <austinf at cetoncorp.com>
---
 libc/sysdeps/linux/mips/clone.S                    |  156 ++++++++++++--------
 .../sysdeps/unix/sysv/linux/mips/Makefile.arch     |    6 +-
 .../nptl/sysdeps/unix/sysv/linux/mips/clone.S      |    2 +
 .../nptl/sysdeps/unix/sysv/linux/mips/vfork.S      |   43 ++++++
 4 files changed, 147 insertions(+), 60 deletions(-)
 create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/mips/clone.S
 create mode 100644 libpthread/nptl/sysdeps/unix/sysv/linux/mips/vfork.S

diff --git a/libc/sysdeps/linux/mips/clone.S b/libc/sysdeps/linux/mips/clone.S
index a53d5c4..7148e9d 100644
--- a/libc/sysdeps/linux/mips/clone.S
+++ b/libc/sysdeps/linux/mips/clone.S
@@ -1,6 +1,6 @@
-/* Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997, 2000, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
-   Contributed by Ralf Baechle <ralf at gnu.ai.mit.edu>, 1996.
+   Contributed by Ralf Baechle <ralf at linux-mips.org>, 1996.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -21,35 +21,43 @@
    and invokes a function in the right context after its all over.  */
 
 #include <features.h>
-#include <asm/unistd.h>
-#include <sys/regdef.h>
-#define _ERRNO_H	1
-#include <bits/errno.h>
 #include <sys/asm.h>
+#include <sysdep.h>
+#define _ERRNO_H        1
+#include <bits/errno.h>
+#ifdef RESET_PID
+#include <tls.h>
+#endif
 
-/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg) */
+#define CLONE_VM      0x00000100
+#define CLONE_THREAD  0x00010000
+
+/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
+	     void *parent_tidptr, void *tls, void *child_tidptr) */
 
 	.text
-.globl   clone ;
-	.align       2;
-	.type         clone, at function;
-	.ent        clone, 0;
-	
-clone:
-	.frame	    sp, 4*SZREG, sp
-#ifdef __PIC__
-#if _MIPS_SIM == _MIPS_SIM_ABI32
-	.set		noreorder
-	.cpload		$25
-	.set		reorder
-	subu		sp,32
-	.cprestore	16
-#else	/* N32 */
-	PTR_SUBU	sp,32	/* fn, arg, gp, pad */
-	.cpsetup	$25, 16, clone
-#endif	/* N32 */
+#if _MIPS_SIM == _ABIO32
+# define EXTRA_LOCALS 1
 #else
-	subu		sp,32
+# define EXTRA_LOCALS 0
+#endif
+LOCALSZ= 4
+FRAMESZ= (((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK
+GPOFF= FRAMESZ-(1*SZREG)
+NESTED(clone,4*SZREG,sp)
+#ifdef __PIC__
+	SETUP_GP
+#endif
+	PTR_SUBU sp, FRAMESZ
+	SETUP_GP64 (GPOFF, clone)
+#ifdef __PIC__
+	SAVE_GP (GPOFF)
+#endif
+#ifdef PROF
+	.set		noat
+	move		$1,ra
+	jal		_mcount
+	.set		at
 #endif
 
 
@@ -58,64 +66,78 @@ clone:
 	beqz		a0,L(error)	/* No NULL function pointers.  */
 	beqz		a1,L(error)	/* No NULL stack pointers.  */
 
-#if _MIPS_SIM != _MIPS_SIM_ABI32
-	and		a1,~(16-1)	/* force alignment */
-#endif
 	PTR_SUBU	a1,32		/* Reserve argument save space.  */
 	PTR_S		a0,0(a1)	/* Save function pointer.  */
 	PTR_S		a3,PTRSIZE(a1)	/* Save argument pointer.  */
+#ifdef RESET_PID
+	LONG_S		a2,(PTRSIZE*2)(a1)	/* Save clone flags.  */
+#endif
 
+	move		a0,a2
+
+	/* Shuffle in the last three arguments - arguments 5, 6, and 7 to
+	   this function, but arguments 3, 4, and 5 to the syscall.  */
+#if _MIPS_SIM == _ABIO32
+	PTR_L		a2,(FRAMESZ+PTRSIZE+PTRSIZE+16)(sp)
+	PTR_S		a2,16(sp)
+	PTR_L		a2,(FRAMESZ+16)(sp)
+	PTR_L		a3,(FRAMESZ+PTRSIZE+16)(sp)
+#else
+	move		a2,a4
+	move		a3,a5
+	move		a4,a6
+#endif
 
 	/* Do the system call */
-	move		a0,a2
 	li		v0,__NR_clone
 	syscall
 
 	bnez		a3,L(error)
-	beqz		v0,L(__thread_start)
+	beqz		v0,L(thread_start)
 
 	/* Successful return from the parent */
-#if _MIPS_SIM != _MIPS_SIM_ABI32
-	.cpreturn
-#endif
-	PTR_ADDU	sp,32
+	RESTORE_GP64
+	PTR_ADDU	sp, FRAMESZ
 	j $31  ; nop
 
 	/* Something bad happened -- no child created */
 L(error):
-#if _MIPS_SIM != _MIPS_SIM_ABI32
-	.cpreturn
-#endif
-	PTR_ADDU	sp,32
-
-	/* uClibc change -- start */
-	move		a0,v0		/* Pass return val to C function. */
-	/* uClibc change -- stop */
-
 #ifdef __PIC__
 	PTR_LA		t9,__syscall_error
+	RESTORE_GP64
+	PTR_ADDU	sp, FRAMESZ
+	/* uClibc change -- start */
+	move            a0,v0           /* Pass return val to C function. */
+	/* uClibc change -- stop */
 	jr		t9
 #else
+	RESTORE_GP64
+	PTR_ADDU	sp, FRAMESZ
+	/* uClibc change -- start */
+	move            a0,v0           /* Pass return val to C function. */
+	/* uClibc change -- stop */
 	j		__syscall_error
 #endif
-	.end  clone
+	END(clone)
 
 /* Load up the arguments to the function.  Put this block of code in
    its own function so that we can terminate the stack trace with our
    debug info.  */
 
-	.globl  __thread_start;
-	.align 2;
-	.ent  __thread_start, 0;
-
-__thread_start:
-L(__thread_start):
-#if _MIPS_SIM == _MIPS_SIM_ABI32
-	.frame	sp, 24, sp
+ENTRY(__thread_start)
+L(thread_start):
 	/* cp is already loaded.  */
-	.cprestore	16
-#endif
+	SAVE_GP (GPOFF)
 	/* The stackframe has been created on entry of clone().  */
+
+#ifdef RESET_PID
+	/* Check and see if we need to reset the PID.  */
+	LONG_L		a0,(PTRSIZE*2)(sp)
+	and		a1,a0,CLONE_THREAD
+	beqz		a1,L(restore_pid)
+L(donepid):
+#endif
+
 	/* Restore the arg for user's function.  */
 	PTR_L		t9,0(sp)	/* Function pointer.  */
 	PTR_L		a0,PTRSIZE(sp)	/* Argument pointer.  */
@@ -126,10 +148,26 @@ L(__thread_start):
 	/* Call _exit rather than doing it inline for breakpoint purposes.  */
 	move		a0,v0
 #ifdef __PIC__
-        PTR_LA          t9,_exit
-        jalr            t9
+	PTR_LA		t9,_exit
+	jalr		t9
 #else
-        jal             _exit
+	jal		_exit
 #endif
-	.end  __thread_start
+
+#ifdef RESET_PID
+L(restore_pid):
+	and		a1,a0,CLONE_VM
+	li		v0,-1
+	bnez		a1,L(gotpid)
+	li		v0,__NR_getpid
+	syscall
+L(gotpid):
+	READ_THREAD_POINTER(v1)
+	INT_S		v0,PID_OFFSET(v1)
+	INT_S		v0,TID_OFFSET(v1)
+	b		L(donepid)
+#endif
+
+	END(__thread_start)
+
 weak_alias(clone, __clone)
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/Makefile.arch b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/Makefile.arch
index 8e7917b..3042cb4 100644
--- a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/Makefile.arch
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/Makefile.arch
@@ -5,10 +5,11 @@
 # Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
 #
 
-libpthread_SSRC = pt-vfork.S
+libpthread_SSRC = pt-vfork.S clone.S
 libpthread_CSRC = pthread_once.c pt-__syscall_rt_sigaction.c
 
 libc_a_CSRC = fork.c
+libc_a_SSRC = clone.S vfork.S
 
 CFLAGS-OMIT-fork.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1
 ifeq ($(UCLIBC_HAS_STDIO_FUTEXES),y)
@@ -19,6 +20,9 @@ CFLAGS-pt-__syscall_rt_sigaction.c = -DNOT_IN_libc=1 -DIS_IN_libpthread=1
 
 ASFLAGS-pt-vfork.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1
 
+ASFLAGS-clone.S = -D_LIBC_REENTRANT
+ASFLAGS-vfork.S = -D_LIBC_REENTRANT
+
 CFLAGS += $(SSP_ALL_CFLAGS)
 #CFLAGS:=$(CFLAGS:-O1=-O2)
 
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/clone.S b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/clone.S
new file mode 100644
index 0000000..858877f
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/clone.S
@@ -0,0 +1,2 @@
+#define RESET_PID
+#include <libc/sysdeps/linux/mips/clone.S>
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/vfork.S
new file mode 100644
index 0000000..9d489e3
--- /dev/null
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/vfork.S
@@ -0,0 +1,43 @@
+/* Copyright (C) 2005, 2006 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.  */
+
+#include <features.h>
+#include <tls.h>
+
+/* Save the PID value.  */
+#define SAVE_PID \
+	READ_THREAD_POINTER(v1);	/* Get the thread pointer.  */	\
+	lw	a2, PID_OFFSET(v1);	/* Load the saved PID.  */	\
+	subu	a2, $0, a2;		/* Negate it.  */		\
+	bnez	a2, 1f;			/* If it was zero... */		\
+	lui	a2, 0x8000;		/* use 0x80000000 instead.  */	\
+1:	sw	a2, PID_OFFSET(v1);	/* Store the temporary PID.  */
+
+/* Restore the old PID value in the parent.  */
+#define RESTORE_PID \
+	beqz	v0, 1f;			/* If we are the parent... */	\
+	READ_THREAD_POINTER(v1);	/* Get the thread pointer.  */	\
+	lw	a2, PID_OFFSET(v1);	/* Load the saved PID.  */	\
+	subu	a2, $0, a2;		/* Re-negate it.  */		\
+	lui	a0, 0x8000;		/* Load 0x80000000... */	\
+	bne	a2, a0, 2f;		/* ... compare against it... */	\
+	li	a2, 0;			/* ... use 0 instead.  */	\
+2:	sw	a2, PID_OFFSET(v1);	/* Restore the PID.  */		\
+1:
+
+#include <../../../../../../../libc/sysdeps/linux/mips/vfork.S>
-- 
1.6.3.3



More information about the uClibc-cvs mailing list