diff options
author | Ulrich Drepper <drepper@redhat.com> | 2003-12-20 23:39:42 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2003-12-20 23:39:42 +0000 |
commit | c0ecb80a43103964d30d8629ce45098fca307081 (patch) | |
tree | 859db25ae2d571c91dabf49a70c8c2e1da535ebe /nptl/sysdeps | |
parent | bbe35eb57144c081d10e76e35e52e9b400202b72 (diff) | |
download | glibc-c0ecb80a43103964d30d8629ce45098fca307081.zip glibc-c0ecb80a43103964d30d8629ce45098fca307081.tar.gz glibc-c0ecb80a43103964d30d8629ce45098fca307081.tar.bz2 |
Update.
2003-12-20 Ulrich Drepper <drepper@redhat.com>
* elf/rtld.c (dl_main): Optimize order or subexpressions in if().
Diffstat (limited to 'nptl/sysdeps')
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/fork.c | 11 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/getpid.c | 26 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/pt-raise.c | 17 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/pthread_kill.c | 5 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/raise.c | 20 |
5 files changed, 62 insertions, 17 deletions
diff --git a/nptl/sysdeps/unix/sysv/linux/fork.c b/nptl/sysdeps/unix/sysv/linux/fork.c index 84bf379..8409744 100644 --- a/nptl/sysdeps/unix/sysv/linux/fork.c +++ b/nptl/sysdeps/unix/sysv/linux/fork.c @@ -117,6 +117,12 @@ __libc_fork (void) pid_t ppid = THREAD_GETMEM (THREAD_SELF, tid); #endif + /* We need to prevent the getpid() code to update the PID field so + that, if a signal arrives in the child very early and the signal + handler uses getpid(), the value returned is correct. */ + pid_t parentpid = THREAD_GETMEM (THREAD_SELF, pid); + THREAD_SETMEM (THREAD_SELF, pid, -parentpid); + #ifdef ARCH_FORK pid = ARCH_FORK (); #else @@ -135,7 +141,7 @@ __libc_fork (void) *__fork_generation_pointer += 4; /* Adjust the PID field for the new process. */ - self->pid = self->tid; + THREAD_SETMEM (self, pid, THREAD_GETMEM (self, tid)); #if HP_TIMING_AVAIL /* The CPU clock of the thread and process have to be set to zero. */ @@ -180,6 +186,9 @@ __libc_fork (void) { assert (THREAD_GETMEM (THREAD_SELF, tid) == ppid); + /* Restore the PID value. */ + THREAD_SETMEM (THREAD_SELF, pid, parentpid); + /* We execute this even if the 'fork' call failed. */ _IO_list_unlock (); diff --git a/nptl/sysdeps/unix/sysv/linux/getpid.c b/nptl/sysdeps/unix/sysv/linux/getpid.c index 75decc1..7efe3f2 100644 --- a/nptl/sysdeps/unix/sysv/linux/getpid.c +++ b/nptl/sysdeps/unix/sysv/linux/getpid.c @@ -22,21 +22,31 @@ #include <sysdep.h> +#ifndef NOT_IN_libc +static pid_t really_getpid (pid_t oldval); +#endif + + pid_t __getpid (void) { - pid_t result; #ifndef NOT_IN_libc - result = THREAD_GETMEM (THREAD_SELF, pid); - if (__builtin_expect (result == 0, 0)) + pid_t result = THREAD_GETMEM (THREAD_SELF, pid); + if (__builtin_expect (result <= 0, 0)) + result = really_getpid (result); + return result; +} + +static pid_t +really_getpid (pid_t oldval) +{ #endif - { - INTERNAL_SYSCALL_DECL (err); - result = INTERNAL_SYSCALL (getpid, err, 0); + INTERNAL_SYSCALL_DECL (err); + pid_t result = INTERNAL_SYSCALL (getpid, err, 0); #ifndef NOT_IN_libc - THREAD_SETMEM (THREAD_SELF, pid, result); + if (oldval == 0) + THREAD_SETMEM (THREAD_SELF, pid, result); #endif - } return result; } libc_hidden_def (__getpid) diff --git a/nptl/sysdeps/unix/sysv/linux/pt-raise.c b/nptl/sysdeps/unix/sysv/linux/pt-raise.c index 2efd761..9161e29 100644 --- a/nptl/sysdeps/unix/sysv/linux/pt-raise.c +++ b/nptl/sysdeps/unix/sysv/linux/pt-raise.c @@ -28,13 +28,22 @@ int raise (sig) int sig; { +#if __ASSUME_TGKILL || defined __NR_tgkill + /* raise is an async-safe function. It could be called while the + fork function temporarily invalidated the PID field. Adjust for + that. */ + pid_t pid = THREAD_GETMEM (THREAD_SELF, pid); + if (__builtin_expect (pid < 0, 0)) + pid = -pid; +#endif + #if __ASSUME_TGKILL - return INLINE_SYSCALL (tgkill, 3, THREAD_GETMEM (THREAD_SELF, pid), - THREAD_GETMEM (THREAD_SELF, tid), sig); + return INLINE_SYSCALL (tgkill, 3, pid, THREAD_GETMEM (THREAD_SELF, tid), + sig); #else # ifdef __NR_tgkill - int res = INLINE_SYSCALL (tgkill, 3, THREAD_GETMEM (THREAD_SELF, pid), - THREAD_GETMEM (THREAD_SELF, tid), sig); + int res = INLINE_SYSCALL (tgkill, 3, pid, THREAD_GETMEM (THREAD_SELF, tid), + sig); if (res != -1 || errno != ENOSYS) return res; # endif diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_kill.c b/nptl/sysdeps/unix/sysv/linux/pthread_kill.c index 6967acd..87577be 100644 --- a/nptl/sysdeps/unix/sysv/linux/pthread_kill.c +++ b/nptl/sysdeps/unix/sysv/linux/pthread_kill.c @@ -44,6 +44,11 @@ __pthread_kill (threadid, signo) /* We have a special syscall to do the work. */ INTERNAL_SYSCALL_DECL (err); + /* One comment: The PID field in the TCB can temporarily be changed + (in fork). But this must not affect this code here. Since this + function would have to be called while the thread is executing + fork, it would have to happen in a signal handler. But this is + no allowed, pthread_kill is not guaranteed to be async-safe. */ int val; #if __ASSUME_TGKILL val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid), diff --git a/nptl/sysdeps/unix/sysv/linux/raise.c b/nptl/sysdeps/unix/sysv/linux/raise.c index 25d3ed8..268ba87 100644 --- a/nptl/sysdeps/unix/sysv/linux/raise.c +++ b/nptl/sysdeps/unix/sysv/linux/raise.c @@ -29,6 +29,9 @@ raise (sig) int sig; { struct pthread *pd = THREAD_SELF; +#if __ASSUME_TGKILL || defined __NR_tgkill + pid_t pid = THREAD_GETMEM (pd, pid); +#endif pid_t selftid = THREAD_GETMEM (pd, tid); if (selftid == 0) { @@ -41,15 +44,24 @@ raise (sig) #endif THREAD_SETMEM (pd, tid, selftid); - /* In this case the TID and PID are the same. */ - THREAD_SETMEM (pd, pid, selftid); + /* We do not set the PID field in the TID here since we might be + called from a signal handler while the thread executes fork. */ + pid = selftid; } +#if __ASSUME_TGKILL || defined __NR_tgkill + else + /* raise is an async-safe function. It could be called while the + fork function temporarily invalidated the PID field. Adjust for + that. */ + if (__builtin_expect (pid < 0, 0)) + pid = -pid; +#endif #if __ASSUME_TGKILL - return INLINE_SYSCALL (tgkill, 3, THREAD_GETMEM (pd, pid), selftid, sig); + return INLINE_SYSCALL (tgkill, 3, pid, selftid, sig); #else # ifdef __NR_tgkill - int res = INLINE_SYSCALL (tgkill, 3, THREAD_GETMEM (pd, pid), selftid, sig); + int res = INLINE_SYSCALL (tgkill, 3, pid, selftid, sig); if (res != -1 || errno != ENOSYS) return res; # endif |