diff options
Diffstat (limited to 'nptl/sysdeps')
-rw-r--r-- | nptl/sysdeps/pthread/bits/libc-lock.h | 26 | ||||
-rw-r--r-- | nptl/sysdeps/pthread/pthread-functions.h | 10 | ||||
-rw-r--r-- | nptl/sysdeps/pthread/setxid.h | 7 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/jmp-unwind.c | 12 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c | 35 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/pthread_kill.c | 18 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/s390/jmp-unwind.c | 15 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c | 2 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h | 26 |
9 files changed, 103 insertions, 48 deletions
diff --git a/nptl/sysdeps/pthread/bits/libc-lock.h b/nptl/sysdeps/pthread/bits/libc-lock.h index 795caa7135..c4c67ea4d3 100644 --- a/nptl/sysdeps/pthread/bits/libc-lock.h +++ b/nptl/sysdeps/pthread/bits/libc-lock.h @@ -1,5 +1,5 @@ /* libc-internal interface for mutex locks. NPTL version. - Copyright (C) 1996-2001, 2002, 2003, 2005 Free Software Foundation, Inc. + Copyright (C) 1996-2003, 2005, 2007 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 @@ -150,13 +150,17 @@ typedef pthread_key_t __libc_key_t; /* Call thread functions through the function pointer table. */ #if defined SHARED && !defined NOT_IN_libc -# define PTF(NAME) __libc_pthread_functions.ptr_##NAME +# define PTFAVAIL(NAME) __libc_pthread_functions_init # define __libc_ptf_call(FUNC, ARGS, ELSE) \ - (PTF(FUNC) != NULL ? PTF(FUNC) ARGS : ELSE) + (__libc_pthread_functions_init ? PTHFCT_CALL (ptr_##FUNC, ARGS) : ELSE) +# define __libc_ptf_call_always(FUNC, ARGS) \ + PTHFCT_CALL (ptr_##FUNC, ARGS) #else -# define PTF(NAME) NAME +# define PTFAVAIL(NAME) (NAME != NULL) # define __libc_ptf_call(FUNC, ARGS, ELSE) \ __libc_maybe_call (FUNC, ARGS, ELSE) +# define __libc_ptf_call_always(FUNC, ARGS) \ + FUNC ARGS #endif @@ -353,8 +357,9 @@ typedef pthread_key_t __libc_key_t; /* Call handler iff the first call. */ #define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \ do { \ - if (PTF(__pthread_once) != NULL) \ - PTF(__pthread_once) (&(ONCE_CONTROL), INIT_FUNCTION); \ + if (PTFAVAIL (__pthread_once)) \ + __libc_ptf_call_always (__pthread_once, (&(ONCE_CONTROL), \ + INIT_FUNCTION)); \ else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) { \ INIT_FUNCTION (); \ (ONCE_CONTROL) |= 2; \ @@ -380,9 +385,10 @@ extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer { struct _pthread_cleanup_buffer _buffer; \ int _avail; \ if (DOIT) { \ - _avail = PTF(_pthread_cleanup_push_defer) != NULL; \ + _avail = PTFAVAIL (_pthread_cleanup_push_defer); \ if (_avail) { \ - PTF(_pthread_cleanup_push_defer) (&_buffer, FCT, ARG); \ + __libc_ptf_call_always (_pthread_cleanup_push_defer, (&_buffer, FCT, \ + ARG)); \ } else { \ _buffer.__routine = (FCT); \ _buffer.__arg = (ARG); \ @@ -394,7 +400,7 @@ extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer /* End critical region with cleanup. */ #define __libc_cleanup_region_end(DOIT) \ if (_avail) { \ - PTF(_pthread_cleanup_pop_restore) (&_buffer, DOIT); \ + __libc_ptf_call_always (_pthread_cleanup_pop_restore, (&_buffer, DOIT));\ } else if (DOIT) \ _buffer.__routine (_buffer.__arg); \ } @@ -402,7 +408,7 @@ extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer /* Sometimes we have to exit the block in the middle. */ #define __libc_cleanup_end(DOIT) \ if (_avail) { \ - PTF(_pthread_cleanup_pop_restore) (&_buffer, DOIT); \ + __libc_ptf_call_always (_pthread_cleanup_pop_restore, (&_buffer, DOIT));\ } else if (DOIT) \ _buffer.__routine (_buffer.__arg) diff --git a/nptl/sysdeps/pthread/pthread-functions.h b/nptl/sysdeps/pthread/pthread-functions.h index 74d24005c3..f8c1e92371 100644 --- a/nptl/sysdeps/pthread/pthread-functions.h +++ b/nptl/sysdeps/pthread/pthread-functions.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2003. @@ -23,6 +23,7 @@ #include <pthread.h> #include <setjmp.h> #include <internaltypes.h> +#include <sysdep.h> struct xid_command; @@ -100,5 +101,12 @@ struct pthread_functions /* Variable in libc.so. */ extern struct pthread_functions __libc_pthread_functions attribute_hidden; +extern int __libc_pthread_functions_init attribute_hidden; + +#define PTHFCT_CALL(fct, params) \ + ({ __typeof (__libc_pthread_functions.fct) __p; \ + __p = __libc_pthread_functions.fct; \ + PTR_DEMANGLE (__p); \ + __p params; }) #endif /* pthread-functions.h */ diff --git a/nptl/sysdeps/pthread/setxid.h b/nptl/sysdeps/pthread/setxid.h index 8ec382f406..aebdbd236a 100644 --- a/nptl/sysdeps/pthread/setxid.h +++ b/nptl/sysdeps/pthread/setxid.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2004 Free Software Foundation, Inc. +/* Copyright (C) 2004, 2007 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 @@ -33,13 +33,12 @@ # define INLINE_SETXID_SYSCALL(name, nr, args...) \ ({ \ int __result; \ - if (__builtin_expect (__libc_pthread_functions.ptr__nptl_setxid \ - != NULL, 0)) \ + if (__builtin_expect (__libc_pthread_functions_init, 0)) \ { \ struct xid_command __cmd; \ __cmd.syscall_no = __NR_##name; \ __SETXID_##nr (__cmd, args); \ - __result = __libc_pthread_functions.ptr__nptl_setxid (&__cmd); \ + __result = PTHFCT_CALL (ptr__nptl_setxid, (&__cmd)); \ } \ else \ __result = INLINE_SYSCALL (name, nr, args); \ diff --git a/nptl/sysdeps/unix/sysv/linux/jmp-unwind.c b/nptl/sysdeps/unix/sysv/linux/jmp-unwind.c index c435eff307..f2795510ab 100644 --- a/nptl/sysdeps/unix/sysv/linux/jmp-unwind.c +++ b/nptl/sysdeps/unix/sysv/linux/jmp-unwind.c @@ -1,5 +1,5 @@ /* Clean up stack frames unwound by longjmp. Linux version. - Copyright (C) 1995, 1997, 2002, 2003 Free Software Foundation, Inc. + Copyright (C) 1995, 1997, 2002, 2003, 2007 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 @@ -29,11 +29,11 @@ void _longjmp_unwind (jmp_buf env, int val) { #ifdef SHARED -# define fptr __libc_pthread_functions.ptr___pthread_cleanup_upto + if (__libc_pthread_functions_init) + PTHFCT_CALL (ptr___pthread_cleanup_upto, (env->__jmpbuf, + CURRENT_STACK_FRAME)); #else -# define fptr __pthread_cleanup_upto + if (__pthread_cleanup_upto != NULL) + __pthread_cleanup_upto (env->__jmpbuf, CURRENT_STACK_FRAME); #endif - - if (fptr != NULL) - fptr (env->__jmpbuf, CURRENT_STACK_FRAME); } diff --git a/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c b/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c index 714ad49428..92a188a2f3 100644 --- a/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c +++ b/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -25,6 +25,7 @@ #include <string.h> #include <pthreadP.h> #include <bits/libc-lock.h> +#include <sysdep.h> #ifdef TLS_MULTIPLE_THREADS_IN_TCB @@ -46,11 +47,29 @@ __libc_pthread_init (ptr, reclaim, functions) __register_atfork (NULL, NULL, reclaim, NULL); #ifdef SHARED - /* We copy the content of the variable pointed to by the FUNCTIONS - parameter to one in libc.so since this means access to the array - can be done with one memory access instead of two. */ - memcpy (&__libc_pthread_functions, functions, - sizeof (__libc_pthread_functions)); + /* Copy the function pointers into an array in libc. This enables + access with just one memory reference but moreso, it prevents + hijacking the function pointers with just one pointer change. We + "encrypt" the function pointers since we cannot write-protect the + array easily enough. */ + union ptrhack + { + struct pthread_functions pf; + void *parr[1]; + } const *src; + union ptrhack *dest; +# define NPTRS (sizeof (struct pthread_functions) / sizeof (void *)) + + src = (const void *) functions; + dest = (void *) &__libc_pthread_functions; + + for (size_t cnt = 0; cnt < NPTRS; ++cnt) + { + void *p = src->parr[cnt]; + PTR_MANGLE (p); + dest->parr[cnt] = p; + } + __libc_pthread_functions_init = 1; #endif #ifndef TLS_MULTIPLE_THREADS_IN_TCB @@ -61,7 +80,7 @@ __libc_pthread_init (ptr, reclaim, functions) #ifdef SHARED libc_freeres_fn (freeres_libptread) { - if (__libc_pthread_functions.ptr_freeres != NULL) - __libc_pthread_functions.ptr_freeres (); + if (__libc_pthread_functions_init) + PTHFCT_CALL (ptr_freeres, ()); } #endif diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_kill.c b/nptl/sysdeps/unix/sysv/linux/pthread_kill.c index 9115d6f40b..75089365c3 100644 --- a/nptl/sysdeps/unix/sysv/linux/pthread_kill.c +++ b/nptl/sysdeps/unix/sysv/linux/pthread_kill.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -33,7 +33,15 @@ __pthread_kill (threadid, signo) struct pthread *pd = (struct pthread *) threadid; /* Make sure the descriptor is valid. */ - if (INVALID_TD_P (pd)) + if (DEBUGGING_P && INVALID_TD_P (pd)) + /* Not a valid thread handle. */ + return ESRCH; + + /* Force load of pd->tid into local variable or register. Otherwise + if a thread exits between ESRCH test and tgkill, we might return + EINVAL, because pd->tid would be cleared by the kernel. */ + pid_t tid = atomic_forced_read (pd->tid); + if (__builtin_expect (tid <= 0, 0)) /* Not a valid thread handle. */ return ESRCH; @@ -53,15 +61,15 @@ __pthread_kill (threadid, signo) int val; #if __ASSUME_TGKILL val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid), - pd->tid, signo); + tid, signo); #else # ifdef __NR_tgkill val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid), - pd->tid, signo); + tid, signo); if (INTERNAL_SYSCALL_ERROR_P (val, err) && INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS) # endif - val = INTERNAL_SYSCALL (tkill, err, 2, pd->tid, signo); + val = INTERNAL_SYSCALL (tkill, err, 2, tid, signo); #endif return (INTERNAL_SYSCALL_ERROR_P (val, err) diff --git a/nptl/sysdeps/unix/sysv/linux/s390/jmp-unwind.c b/nptl/sysdeps/unix/sysv/linux/s390/jmp-unwind.c index 36886f58a4..3c18df2c4f 100644 --- a/nptl/sysdeps/unix/sysv/linux/s390/jmp-unwind.c +++ b/nptl/sysdeps/unix/sysv/linux/s390/jmp-unwind.c @@ -1,5 +1,5 @@ /* Clean up stack frames unwound by longjmp. Linux/s390 version. - Copyright (C) 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2007 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 @@ -28,14 +28,13 @@ extern void __pthread_cleanup_upto (__jmp_buf env, char *targetframe); void _longjmp_unwind (jmp_buf env, int val) { + unsigned char local_var; + #ifdef SHARED -# define fptr __libc_pthread_functions.ptr___pthread_cleanup_upto + if (__libc_pthread_functions_init) + PTHFCT_CALL (ptr___pthread_cleanup_upto, (env->__jmpbuf, &local_var)); #else -# define fptr __pthread_cleanup_upto + if (__pthread_cleanup_upto != NULL) + __pthread_cleanup_upto (env->__jmpbuf, &local_var); #endif - - unsigned char local_var; - - if (fptr != NULL) - fptr (env->__jmpbuf, &local_var); } diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c index 7613863bba..55d20eb8f8 100644 --- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c @@ -1 +1 @@ -#include "../../../../../../pthread/pthread_barrier_wait.c" +#include "../../../../../../../pthread_barrier_wait.c" diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h index 97085bf018..bb988f3b2b 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -35,6 +35,7 @@ #define SYS_futex 202 #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 +#define FUTEX_CMP_REQUEUE 4 #define FUTEX_LOCK_PI 6 #define FUTEX_UNLOCK_PI 7 #define FUTEX_TRYLOCK_PI 8 @@ -150,7 +151,7 @@ LLL_STUB_UNWIND_INFO_END #define lll_futex_wait(futex, val) \ ({ \ int __status; \ - register __typeof (val) _val asm ("edx") = (val); \ + register __typeof (val) _val __asm ("edx") = (val); \ __asm __volatile ("xorq %%r10, %%r10\n\t" \ "syscall" \ : "=a" (__status) \ @@ -163,9 +164,9 @@ LLL_STUB_UNWIND_INFO_END #define lll_futex_timed_wait(futex, val, timeout) \ ({ \ - register const struct timespec *__to __asm__ ("r10") = timeout; \ + register const struct timespec *__to __asm ("r10") = timeout; \ int __status; \ - register __typeof (val) _val asm ("edx") = (val); \ + register __typeof (val) _val __asm ("edx") = (val); \ __asm __volatile ("syscall" \ : "=a" (__status) \ : "0" (SYS_futex), "D" (futex), "S" (FUTEX_WAIT), \ @@ -178,7 +179,7 @@ LLL_STUB_UNWIND_INFO_END #define lll_futex_wake(futex, nr) \ do { \ int __ignore; \ - register __typeof (nr) _nr asm ("edx") = (nr); \ + register __typeof (nr) _nr __asm ("edx") = (nr); \ __asm __volatile ("syscall" \ : "=a" (__ignore) \ : "0" (SYS_futex), "D" (futex), "S" (FUTEX_WAKE), \ @@ -423,6 +424,21 @@ extern int __lll_mutex_unlock_wait (int *__futex) attribute_hidden; : "cx", "r11", "cc", "memory"); }) +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_requeue(ftx, nr_wake, nr_move, mutex, val) \ + ({ int __res; \ + register int __nr_move __asm ("r10") = nr_move; \ + register void *__mutex __asm ("r8") = mutex; \ + register int __val __asm ("r9") = val; \ + __asm __volatile ("syscall" \ + : "=a" (__res) \ + : "0" (__NR_futex), "D" ((void *) ftx), \ + "S" (FUTEX_CMP_REQUEUE), "d" (nr_wake), \ + "r" (__nr_move), "r" (__mutex), "r" (__val) \ + : "cx", "r11", "cc", "memory"); \ + __res < 0; }) + + #define lll_mutex_islocked(futex) \ (futex != LLL_MUTEX_LOCK_INITIALIZER) |