diff options
Diffstat (limited to 'sysdeps/unix/sysv/linux')
-rw-r--r-- | sysdeps/unix/sysv/linux/mips/bits/siginfo.h | 9 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/mips/clone.S | 60 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/mips/mips32/sysdep.h | 285 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/mips/vfork.S | 98 |
4 files changed, 309 insertions, 143 deletions
diff --git a/sysdeps/unix/sysv/linux/mips/bits/siginfo.h b/sysdeps/unix/sysv/linux/mips/bits/siginfo.h index 54eba41d6e..787e365139 100644 --- a/sysdeps/unix/sysv/linux/mips/bits/siginfo.h +++ b/sysdeps/unix/sysv/linux/mips/bits/siginfo.h @@ -1,5 +1,5 @@ /* siginfo_t, sigevent and constants. Linux/MIPS version. - Copyright (C) 1997, 1998, 2000, 2001, 2002, 2003, 2004 + Copyright (C) 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -300,10 +300,11 @@ enum # define SIGEV_SIGNAL SIGEV_SIGNAL SIGEV_NONE, /* Other notification: meaningless. */ # define SIGEV_NONE SIGEV_NONE - SIGEV_CALLBACK, /* Deliver via thread creation. */ -# define SIGEV_CALLBACK SIGEV_CALLBACK - SIGEV_THREAD /* Deliver via thread creation. */ + SIGEV_THREAD, /* Deliver via thread creation. */ # define SIGEV_THREAD SIGEV_THREAD + + SIGEV_THREAD_ID = 4 /* Send signal to specific thread. */ +#define SIGEV_THREAD_ID SIGEV_THREAD_ID }; #endif /* have _SIGNAL_H. */ diff --git a/sysdeps/unix/sysv/linux/mips/clone.S b/sysdeps/unix/sysv/linux/mips/clone.S index 043f5921cb..8b8e0072f5 100644 --- a/sysdeps/unix/sysv/linux/mips/clone.S +++ b/sysdeps/unix/sysv/linux/mips/clone.S @@ -1,4 +1,4 @@ -/* Copyright (C) 1996, 1997, 2000, 2003 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@linux-mips.org>, 1996. @@ -24,11 +24,23 @@ #include <sysdep.h> #define _ERRNO_H 1 #include <bits/errno.h> +#ifdef RESET_PID +#include <tls.h> +#endif + +#define CLONE_VM 0x00000100 +#define CLONE_THREAD 0x00010000 -/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg) */ +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, + void *parent_tidptr, void *tls, void *child_tidptr) */ .text -LOCALSZ= 1 +#if _MIPS_SIM == _ABIO32 +# define EXTRA_LOCALS 1 +#else +# define EXTRA_LOCALS 0 +#endif +LOCALSZ= 4 FRAMESZ= (((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK GPOFF= FRAMESZ-(1*SZREG) NESTED(__clone,4*SZREG,sp) @@ -56,10 +68,26 @@ NESTED(__clone,4*SZREG,sp) 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 @@ -94,6 +122,15 @@ L(thread_start): /* cp is already loaded. */ 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. */ @@ -109,6 +146,21 @@ L(thread_start): #else jal _exit #endif + +#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/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h b/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h index 682ec3d6aa..3da2412259 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h +++ b/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000, 2002, 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2000, 2002, 2003, 2004, 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 @@ -48,12 +48,12 @@ #undef INLINE_SYSCALL #define INLINE_SYSCALL(name, nr, args...) \ ({ INTERNAL_SYSCALL_DECL(err); \ - long result_var = INTERNAL_SYSCALL (name, err, nr, args); \ - if ( INTERNAL_SYSCALL_ERROR_P (result_var, err) ) \ - { \ - __set_errno (INTERNAL_SYSCALL_ERRNO (result_var, err)); \ - result_var = -1L; \ - } \ + long result_var = INTERNAL_SYSCALL (name, err, nr, args); \ + if ( INTERNAL_SYSCALL_ERROR_P (result_var, err) ) \ + { \ + __set_errno (INTERNAL_SYSCALL_ERRNO (result_var, err)); \ + result_var = -1L; \ + } \ result_var; }) #undef INTERNAL_SYSCALL_DECL @@ -66,203 +66,218 @@ #define INTERNAL_SYSCALL_ERRNO(val, err) (val) #undef INTERNAL_SYSCALL -#define INTERNAL_SYSCALL(name, err, nr, args...) internal_syscall##nr(name, err, args) +#define INTERNAL_SYSCALL(name, err, nr, args...) \ + internal_syscall##nr (, "li\t$2, %2\t\t\t# " #name "\n\t", \ + "i" (SYS_ify (name)), err, args) -#define internal_syscall0(name, err, dummy...) \ -({ \ +#undef INTERNAL_SYSCALL_NCS +#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ + internal_syscall##nr (= number, , "r" (__v0), err, args) + +#define internal_syscall0(ncs_init, cs_init, input, err, dummy...) \ +({ \ long _sys_result; \ \ { \ - register long __v0 asm("$2"); \ - register long __a3 asm("$7"); \ - __asm__ volatile ( \ - ".set\tnoreorder\n\t" \ - "li\t$2, %2\t\t\t# " #name "\n\t" \ - "syscall\n\t" \ - ".set reorder" \ - : "=r" (__v0), "=r" (__a3) \ - : "i" (SYS_ify(name)) \ - : __SYSCALL_CLOBBERS); \ + register long __v0 asm("$2") ncs_init; \ + register long __a3 asm("$7"); \ + __asm__ volatile ( \ + ".set\tnoreorder\n\t" \ + cs_init \ + "syscall\n\t" \ + ".set reorder" \ + : "=r" (__v0), "=r" (__a3) \ + : input \ + : __SYSCALL_CLOBBERS); \ err = __a3; \ _sys_result = __v0; \ } \ _sys_result; \ }) -#define internal_syscall1(name, err, arg1) \ -({ \ +#define internal_syscall1(ncs_init, cs_init, input, err, arg1) \ +({ \ long _sys_result; \ \ { \ - register long __v0 asm("$2"); \ - register long __a0 asm("$4") = (long) arg1; \ - register long __a3 asm("$7"); \ - __asm__ volatile ( \ - ".set\tnoreorder\n\t" \ - "li\t$2, %3\t\t\t# " #name "\n\t" \ - "syscall\n\t" \ - ".set reorder" \ - : "=r" (__v0), "=r" (__a3) \ - : "r" (__a0), "i" (SYS_ify(name)) \ - : __SYSCALL_CLOBBERS); \ + register long __v0 asm("$2") ncs_init; \ + register long __a0 asm("$4") = (long) arg1; \ + register long __a3 asm("$7"); \ + __asm__ volatile ( \ + ".set\tnoreorder\n\t" \ + cs_init \ + "syscall\n\t" \ + ".set reorder" \ + : "=r" (__v0), "=r" (__a3) \ + : input, "r" (__a0) \ + : __SYSCALL_CLOBBERS); \ err = __a3; \ _sys_result = __v0; \ } \ _sys_result; \ }) -#define internal_syscall2(name, err, arg1, arg2) \ -({ \ +#define internal_syscall2(ncs_init, cs_init, input, err, arg1, arg2) \ +({ \ long _sys_result; \ \ { \ - register long __v0 asm("$2"); \ - register long __a0 asm("$4") = (long) arg1; \ - register long __a1 asm("$5") = (long) arg2; \ - register long __a3 asm("$7"); \ - __asm__ volatile ( \ - ".set\tnoreorder\n\t" \ - "li\t$2, %4\t\t\t# " #name "\n\t" \ - "syscall\n\t" \ - ".set\treorder" \ - : "=r" (__v0), "=r" (__a3) \ - : "r" (__a0), "r" (__a1), "i" (SYS_ify(name)) \ - : __SYSCALL_CLOBBERS); \ + register long __v0 asm("$2") ncs_init; \ + register long __a0 asm("$4") = (long) arg1; \ + register long __a1 asm("$5") = (long) arg2; \ + register long __a3 asm("$7"); \ + __asm__ volatile ( \ + ".set\tnoreorder\n\t" \ + cs_init \ + "syscall\n\t" \ + ".set\treorder" \ + : "=r" (__v0), "=r" (__a3) \ + : input, "r" (__a0), "r" (__a1) \ + : __SYSCALL_CLOBBERS); \ err = __a3; \ _sys_result = __v0; \ } \ _sys_result; \ }) -#define internal_syscall3(name, err, arg1, arg2, arg3) \ -({ \ +#define internal_syscall3(ncs_init, cs_init, input, err, arg1, arg2, arg3)\ +({ \ long _sys_result; \ \ { \ - register long __v0 asm("$2"); \ - register long __a0 asm("$4") = (long) arg1; \ - register long __a1 asm("$5") = (long) arg2; \ - register long __a2 asm("$6") = (long) arg3; \ - register long __a3 asm("$7"); \ - __asm__ volatile ( \ - ".set\tnoreorder\n\t" \ - "li\t$2, %5\t\t\t# " #name "\n\t" \ - "syscall\n\t" \ - ".set\treorder" \ - : "=r" (__v0), "=r" (__a3) \ - : "r" (__a0), "r" (__a1), "r" (__a2), "i" (SYS_ify(name)) \ - : __SYSCALL_CLOBBERS); \ + register long __v0 asm("$2") ncs_init; \ + register long __a0 asm("$4") = (long) arg1; \ + register long __a1 asm("$5") = (long) arg2; \ + register long __a2 asm("$6") = (long) arg3; \ + register long __a3 asm("$7"); \ + __asm__ volatile ( \ + ".set\tnoreorder\n\t" \ + cs_init \ + "syscall\n\t" \ + ".set\treorder" \ + : "=r" (__v0), "=r" (__a3) \ + : input, "r" (__a0), "r" (__a1), "r" (__a2) \ + : __SYSCALL_CLOBBERS); \ err = __a3; \ _sys_result = __v0; \ } \ _sys_result; \ }) -#define internal_syscall4(name, err, arg1, arg2, arg3, arg4) \ -({ \ +#define internal_syscall4(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4)\ +({ \ long _sys_result; \ \ { \ - register long __v0 asm("$2"); \ - register long __a0 asm("$4") = (long) arg1; \ - register long __a1 asm("$5") = (long) arg2; \ - register long __a2 asm("$6") = (long) arg3; \ - register long __a3 asm("$7") = (long) arg4; \ - __asm__ volatile ( \ - ".set\tnoreorder\n\t" \ - "li\t$2, %5\t\t\t# " #name "\n\t" \ - "syscall\n\t" \ - ".set\treorder" \ - : "=r" (__v0), "+r" (__a3) \ - : "r" (__a0), "r" (__a1), "r" (__a2), "i" (SYS_ify(name)) \ - : __SYSCALL_CLOBBERS); \ + register long __v0 asm("$2") ncs_init; \ + register long __a0 asm("$4") = (long) arg1; \ + register long __a1 asm("$5") = (long) arg2; \ + register long __a2 asm("$6") = (long) arg3; \ + register long __a3 asm("$7") = (long) arg4; \ + __asm__ volatile ( \ + ".set\tnoreorder\n\t" \ + cs_init \ + "syscall\n\t" \ + ".set\treorder" \ + : "=r" (__v0), "+r" (__a3) \ + : input, "r" (__a0), "r" (__a1), "r" (__a2) \ + : __SYSCALL_CLOBBERS); \ err = __a3; \ _sys_result = __v0; \ } \ _sys_result; \ }) -#define internal_syscall5(name, err, arg1, arg2, arg3, arg4, arg5) \ -({ \ +/* We need to use a frame pointer for the functions in which we + adjust $sp around the syscall, or debug information and unwind + information will be $sp relative and thus wrong during the syscall. As + of GCC 3.4.3, this is sufficient. */ +#define FORCE_FRAME_POINTER alloca (4) + +#define internal_syscall5(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5)\ +({ \ long _sys_result; \ \ + FORCE_FRAME_POINTER; \ { \ - register long __v0 asm("$2"); \ - register long __a0 asm("$4") = (long) arg1; \ - register long __a1 asm("$5") = (long) arg2; \ - register long __a2 asm("$6") = (long) arg3; \ - register long __a3 asm("$7") = (long) arg4; \ - __asm__ volatile ( \ - ".set\tnoreorder\n\t" \ - "subu\t$29, 32\n\t" \ - "sw\t%6, 16($29)\n\t" \ - "li\t$2, %5\t\t\t# " #name "\n\t" \ - "syscall\n\t" \ - "addiu\t$29, 32\n\t" \ - ".set\treorder" \ - : "=r" (__v0), "+r" (__a3) \ - : "r" (__a0), "r" (__a1), "r" (__a2), "i" (SYS_ify(name)), \ - "r" ((long)arg5) \ - : __SYSCALL_CLOBBERS); \ + register long __v0 asm("$2") ncs_init; \ + register long __a0 asm("$4") = (long) arg1; \ + register long __a1 asm("$5") = (long) arg2; \ + register long __a2 asm("$6") = (long) arg3; \ + register long __a3 asm("$7") = (long) arg4; \ + __asm__ volatile ( \ + ".set\tnoreorder\n\t" \ + "subu\t$29, 32\n\t" \ + "sw\t%6, 16($29)\n\t" \ + cs_init \ + "syscall\n\t" \ + "addiu\t$29, 32\n\t" \ + ".set\treorder" \ + : "=r" (__v0), "+r" (__a3) \ + : input, "r" (__a0), "r" (__a1), "r" (__a2), \ + "r" ((long)arg5) \ + : __SYSCALL_CLOBBERS); \ err = __a3; \ _sys_result = __v0; \ } \ _sys_result; \ }) -#define internal_syscall6(name, err, arg1, arg2, arg3, arg4, arg5, arg6)\ -({ \ +#define internal_syscall6(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6)\ +({ \ long _sys_result; \ \ + FORCE_FRAME_POINTER; \ { \ - register long __v0 asm("$2"); \ - register long __a0 asm("$4") = (long) arg1; \ - register long __a1 asm("$5") = (long) arg2; \ - register long __a2 asm("$6") = (long) arg3; \ - register long __a3 asm("$7") = (long) arg4; \ - __asm__ volatile ( \ - ".set\tnoreorder\n\t" \ - "subu\t$29, 32\n\t" \ - "sw\t%6, 16($29)\n\t" \ - "sw\t%7, 20($29)\n\t" \ - "li\t$2, %5\t\t\t# " #name "\n\t" \ - "syscall\n\t" \ - "addiu\t$29, 32\n\t" \ - ".set\treorder" \ - : "=r" (__v0), "+r" (__a3) \ - : "r" (__a0), "r" (__a1), "r" (__a2), "i" (SYS_ify(name)), \ + register long __v0 asm("$2") ncs_init; \ + register long __a0 asm("$4") = (long) arg1; \ + register long __a1 asm("$5") = (long) arg2; \ + register long __a2 asm("$6") = (long) arg3; \ + register long __a3 asm("$7") = (long) arg4; \ + __asm__ volatile ( \ + ".set\tnoreorder\n\t" \ + "subu\t$29, 32\n\t" \ + "sw\t%6, 16($29)\n\t" \ + "sw\t%7, 20($29)\n\t" \ + cs_init \ + "syscall\n\t" \ + "addiu\t$29, 32\n\t" \ + ".set\treorder" \ + : "=r" (__v0), "+r" (__a3) \ + : input, "r" (__a0), "r" (__a1), "r" (__a2), \ "r" ((long)arg5), "r" ((long)arg6) \ - : __SYSCALL_CLOBBERS); \ + : __SYSCALL_CLOBBERS); \ err = __a3; \ _sys_result = __v0; \ } \ _sys_result; \ }) -#define internal_syscall7(name, err, arg1, arg2, arg3, arg4, arg5, arg6, arg7)\ -({ \ +#define internal_syscall7(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6, arg7)\ +({ \ long _sys_result; \ \ + FORCE_FRAME_POINTER; \ { \ - register long __v0 asm("$2"); \ - register long __a0 asm("$4") = (long) arg1; \ - register long __a1 asm("$5") = (long) arg2; \ - register long __a2 asm("$6") = (long) arg3; \ - register long __a3 asm("$7") = (long) arg4; \ - __asm__ volatile ( \ - ".set\tnoreorder\n\t" \ - "subu\t$29, 32\n\t" \ - "sw\t%6, 16($29)\n\t" \ - "sw\t%7, 20($29)\n\t" \ - "sw\t%8, 24($29)\n\t" \ - "li\t$2, %5\t\t\t# " #name "\n\t" \ - "syscall\n\t" \ - "addiu\t$29, 32\n\t" \ - ".set\treorder" \ - : "=r" (__v0), "+r" (__a3) \ - : "r" (__a0), "r" (__a1), "r" (__a2), "i" (SYS_ify(name)), \ + register long __v0 asm("$2") ncs_init; \ + register long __a0 asm("$4") = (long) arg1; \ + register long __a1 asm("$5") = (long) arg2; \ + register long __a2 asm("$6") = (long) arg3; \ + register long __a3 asm("$7") = (long) arg4; \ + __asm__ volatile ( \ + ".set\tnoreorder\n\t" \ + "subu\t$29, 32\n\t" \ + "sw\t%6, 16($29)\n\t" \ + "sw\t%7, 20($29)\n\t" \ + "sw\t%8, 24($29)\n\t" \ + cs_init \ + "syscall\n\t" \ + "addiu\t$29, 32\n\t" \ + ".set\treorder" \ + : "=r" (__v0), "+r" (__a3) \ + : input, "r" (__a0), "r" (__a1), "r" (__a2), \ "r" ((long)arg5), "r" ((long)arg6), "r" ((long)arg7) \ - : __SYSCALL_CLOBBERS); \ + : __SYSCALL_CLOBBERS); \ err = __a3; \ _sys_result = __v0; \ } \ diff --git a/sysdeps/unix/sysv/linux/mips/vfork.S b/sysdeps/unix/sysv/linux/mips/vfork.S new file mode 100644 index 0000000000..1383ddc6a7 --- /dev/null +++ b/sysdeps/unix/sysv/linux/mips/vfork.S @@ -0,0 +1,98 @@ +/* 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> +#include <asm/unistd.h> +#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) |