diff options
-rw-r--r-- | ChangeLog | 19 | ||||
-rw-r--r-- | nptl/ChangeLog | 7 | ||||
-rw-r--r-- | nptl/Makefile | 3 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/x86_64/clone.S | 2 | ||||
-rw-r--r-- | nptl/tst-getpid1.c | 99 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/i386/clone.S | 36 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/x86_64/clone.S | 20 |
7 files changed, 175 insertions, 11 deletions
diff --git a/ChangeLog b/ChangeLog index 37b677a4b0..7746d6291c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2004-12-04 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/i386/clone.S: Add support for NPTL where + the PID is stored at userlevel and needs to be reset when CLONE_THREAD + is not used. + * sysdeps/unix/sysv/linux/86_64/clone.S: Likewise. + 2004-11-18 Daniel Jacobowitz <dan@codesourcery.com> * sysdeps/arm/sysdep.h: Define __USE_BX__ if bx is available. @@ -9,12 +16,12 @@ * sysdeps/arm/strlen.S: Use DO_RET. * sysdeps/unix/arm/brk.S, sysdeps/unix/arm/fork.S, sysdeps/unix/arm/sysdep.S, sysdeps/unix/arm/sysdep.h: Likewise. - * sysdeps/unix/sysv/linux/arm/clone.S, - sysdeps/unix/sysv/linux/arm/mmap.S, - sysdeps/unix/sysv/linux/arm/mmap64.S, - sysdeps/unix/sysv/linux/arm/socket.S, - sysdeps/unix/sysv/linux/arm/sysdep.h, - sysdeps/unix/sysv/linux/arm/vfork.S: Update uses of RETINSTR. + * sysdeps/unix/sysv/linux/arm/clone.S: Update uses of RETINSTR. + * sysdeps/unix/sysv/linux/arm/mmap.S: Likewise. + * sysdeps/unix/sysv/linux/arm/mmap64.S: Likewise. + * sysdeps/unix/sysv/linux/arm/socket.S: Likewise. + * sysdeps/unix/sysv/linux/arm/sysdep.h: Likewise. + * sysdeps/unix/sysv/linux/arm/vfork.S: Likewise. 2004-12-02 Roland McGrath <roland@redhat.com> diff --git a/nptl/ChangeLog b/nptl/ChangeLog index f045eea012..db184cf140 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,3 +1,10 @@ +2004-12-04 Ulrich Drepper <drepper@redhat.com> + + * Makefile (tests): Add tst-getpid1. + * tst-getpid1.c: New file. + * sysdeps/unix/sysv/linux/i386/clone.S: New file. + * sysdeps/unix/sysv/linux/x86_64/clone.S: New file. + 2004-12-02 Roland McGrath <roland@redhat.com> * Makefile (libpthread-nonshared): Variable removed. diff --git a/nptl/Makefile b/nptl/Makefile index f9993dd1fd..ecd5e52cdb 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -240,7 +240,8 @@ tests = tst-attr1 tst-attr2 tst-attr3 \ tst-sched1 \ tst-backtrace1 \ tst-oddstacklimit \ - tst-vfork1 tst-vfork2 tst-vfork1x tst-vfork2x + tst-vfork1 tst-vfork2 tst-vfork1x tst-vfork2x \ + tst-getpid1 xtests = tst-setuid1 tst-setuid1-static # Files which must not be linked with libpthread. diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/clone.S b/nptl/sysdeps/unix/sysv/linux/x86_64/clone.S new file mode 100644 index 0000000000..dfa6adb3e2 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/clone.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include <sysdeps/unix/sysv/linux/x86_64/clone.S> diff --git a/nptl/tst-getpid1.c b/nptl/tst-getpid1.c new file mode 100644 index 0000000000..9d637159c4 --- /dev/null +++ b/nptl/tst-getpid1.c @@ -0,0 +1,99 @@ +#include <sched.h> +#include <signal.h> +#include <stdio.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/wait.h> + +static int sig; + +static int +f (void *a) +{ + puts ("in f"); + union sigval sival; + sival.sival_int = getpid (); + printf ("pid = %d\n", sival.sival_int); + if (sigqueue (getppid (), sig, sival) != 0) + return 1; + return 0; +} + + +static int +do_test (void) +{ + int mypid = getpid (); + + sig = SIGRTMIN; + sigset_t ss; + sigemptyset (&ss); + sigaddset (&ss, sig); + if (sigprocmask (SIG_BLOCK, &ss, NULL) != 0) + { + printf ("sigprocmask failed: %m\n"); + return 1; + } + + char st[128 * 1024]; + pid_t p = clone (f, st + sizeof (st), 0, 0); + if (p == -1) + { + printf("clone failed: %m\n"); + return 1; + } + printf ("new thread: %d\n", (int) p); + + siginfo_t si; + do + if (sigwaitinfo (&ss, &si) < 0) + { + printf("sigwaitinfo failed: %m\n"); + kill (p, SIGKILL); + return 1; + } + while (si.si_signo != sig || si.si_code != SI_QUEUE); + + if (si.si_int != (int) p) + { + printf ("expected PID %d, got si_int %d\n", (int) p, si.si_int); + kill (p, SIGKILL); + return 1; + } + + if (si.si_pid != p) + { + printf ("expected PID %d, got si_pid %d\n", (int) p, (int) si.si_pid); + kill (p, SIGKILL); + return 1; + } + + int e; + if (waitpid (p, &e, __WCLONE) != p) + { + puts ("waitpid failed"); + kill (p, SIGKILL); + return 1; + } + if (!WIFEXITED (e)) + { + puts ("did not terminate correctly"); + return 1; + } + if (WEXITSTATUS (e) != 0) + { + printf ("exit code %d\n", WEXITSTATUS (e)); + return 1; + } + + if (getpid () != mypid) + { + puts ("my PID changed"); + return 1; + } + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/sysdeps/unix/sysv/linux/i386/clone.S b/sysdeps/unix/sysv/linux/i386/clone.S index 94c6a72548..acd43dfb0b 100644 --- a/sysdeps/unix/sysv/linux/i386/clone.S +++ b/sysdeps/unix/sysv/linux/i386/clone.S @@ -1,4 +1,4 @@ -/* Copyright (C) 1996,1997,98,99,2000,02,03 Free Software Foundation, Inc. +/* Copyright (C) 1996,1997,98,99,2000,02,03,04 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Richard Henderson (rth@tamu.edu) @@ -42,6 +42,9 @@ #define __NR_clone 120 #define SYS_clone 120 +#define CLONE_VM 0x00000100 +#define CLONE_THREAD 0x00010000 + .text ENTRY (BP_SYM (__clone)) /* Sanity check arguments. */ @@ -74,7 +77,9 @@ ENTRY (BP_SYM (__clone)) movl %eax,8(%ecx) /* Don't leak any information. */ movl $0,4(%ecx) +#ifndef RESET_PID movl $0,(%ecx) +#endif /* Do the system call */ pushl %ebx @@ -85,6 +90,12 @@ ENTRY (BP_SYM (__clone)) movl FLAGS+12(%esp),%ebx movl CTID+12(%esp),%edi movl $SYS_ify(clone),%eax + +#ifdef RESET_PID + /* Remember the flag value. */ + movl %ebx, (%ecx) +#endif + int $0x80 popl %edi popl %esi @@ -98,7 +109,13 @@ L(pseudo_end): ret L(thread_start): - subl %ebp,%ebp /* terminate the stack frame */ + /* Note: %esi is zero. */ + movl %esi,%ebp /* terminate the stack frame */ +#ifdef RESET_PID + testl $CLONE_THREAD, %edi + je L(newpid) +L(haspid): +#endif call *%ebx #ifdef PIC call L(here) @@ -110,6 +127,21 @@ L(here): movl $SYS_ify(exit), %eax int $0x80 +#ifdef RESET_PID + .subsection 2 +L(newpid): + testl $CLONE_VM, %edi + movl $-1, %eax + jne L(nomoregetpid) + movl $SYS_ify(getpid), %eax + ENTER_KERNEL +L(nomoregetpid): + movl %eax, %gs:PID + movl %eax, %gs:TID + jmp L(haspid) + .previous +#endif + PSEUDO_END (BP_SYM (__clone)) weak_alias (BP_SYM (__clone), BP_SYM (clone)) diff --git a/sysdeps/unix/sysv/linux/x86_64/clone.S b/sysdeps/unix/sysv/linux/x86_64/clone.S index d182fe2f9e..9695e1eaf8 100644 --- a/sysdeps/unix/sysv/linux/x86_64/clone.S +++ b/sysdeps/unix/sysv/linux/x86_64/clone.S @@ -26,6 +26,9 @@ #include <bp-sym.h> #include <bp-asm.h> +#define CLONE_VM 0x00000100 +#define CLONE_THREAD 0x00010000 + /* The userland implementation is: int clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg), the kernel entry is: @@ -80,16 +83,29 @@ ENTRY (BP_SYM (__clone)) testq %rax,%rax jl SYSCALL_ERROR_LABEL - jz thread_start + jz L(thread_start) L(pseudo_end): ret -thread_start: +L(thread_start): /* Clear the frame pointer. The ABI suggests this be done, to mark the outermost frame obviously. */ xorq %rbp, %rbp +#ifdef RESET_PID + testq $CLONE_THREAD, %rdi + jne 1f + testq $CLONE_VM, %rdi + movl $-1, %eax + jne 2f + movq $SYS_ify(getpid), %rax + syscall +2: movl %eax, %fs:PID + movl %eax, %fs:TID +1: +#endif + /* Set up arguments for the function call. */ popq %rax /* Function to call. */ popq %rdi /* Argument. */ |