summaryrefslogtreecommitdiff
path: root/nptl/sysdeps/unix
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2007-01-17 10:42:43 +0000
committerJakub Jelinek <jakub@redhat.com>2007-01-17 10:42:43 +0000
commitaf98d46f5a025ae33c60ddb1a5edc753fb714bc5 (patch)
tree24a3c5cb0bfc6163b52ae74ac205f0e175beee87 /nptl/sysdeps/unix
parent1f09da09fed864c91288ff91295114fa5202edaa (diff)
Updated to fedora-glibc-20070117T0857
Diffstat (limited to 'nptl/sysdeps/unix')
-rw-r--r--nptl/sysdeps/unix/sysv/linux/jmp-unwind.c12
-rw-r--r--nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c35
-rw-r--r--nptl/sysdeps/unix/sysv/linux/pthread_kill.c18
-rw-r--r--nptl/sysdeps/unix/sysv/linux/s390/jmp-unwind.c15
-rw-r--r--nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c2
-rw-r--r--nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h26
6 files changed, 75 insertions, 33 deletions
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)