diff options
-rw-r--r-- | libc/sysdeps/linux/mips/clone.S | 156 | ||||
-rw-r--r-- | libpthread/nptl/sysdeps/unix/sysv/linux/mips/Makefile.arch | 6 | ||||
-rw-r--r-- | libpthread/nptl/sysdeps/unix/sysv/linux/mips/clone.S | 2 | ||||
-rw-r--r-- | libpthread/nptl/sysdeps/unix/sysv/linux/mips/vfork.S | 43 |
4 files changed, 147 insertions, 60 deletions
diff --git a/libc/sysdeps/linux/mips/clone.S b/libc/sysdeps/linux/mips/clone.S index a53d5c492..7148e9d2c 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@gnu.ai.mit.edu>, 1996. + Contributed by Ralf Baechle <ralf@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,@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 8e7917bb0..3042cb480 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 000000000..858877f07 --- /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 000000000..9d489e303 --- /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> |