2003-12-20  Ulrich Drepper  <drepper@redhat.com>

	* elf/rtld.c (dl_main): Optimize order or subexpressions in if().
This commit is contained in:
Ulrich Drepper 2003-12-20 23:39:42 +00:00
parent bbe35eb571
commit c0ecb80a43
9 changed files with 82 additions and 18 deletions

View File

@ -1,3 +1,7 @@
2003-12-20 Ulrich Drepper <drepper@redhat.com>
* elf/rtld.c (dl_main): Optimize order or subexpressions in if().
2003-12-18 Ulrich Drepper <drepper@redhat.com>
* stdio-common/printf_fp.c: Add support to use alternative decimal

View File

@ -2,6 +2,15 @@
* sysdeps/unix/sysv/linux/Makefile (CFLAGS-getpid.c): Define.
* sysdeps/unix/sysv/linux/getpid.c: New file.
* pthread_cancel.c: Add comment explaining use of PID field.
* sysdeps/unix/sysv/linux/pthread_kill.c: Likewise.
* pthread_getattr_np.c: Use abs() when comparing PID and TID fields.
* sysdeps/unix/sysv/linux/fork.c: Negate PID field of parent
temporarily to signal the field must not be relied on and updated
by getpid().
* sysdeps/unix/sysv/linux/pt-raise.c: Handle case where PID is
temporarily negative.
* sysdeps/unix/sysv/linux/raise.c: Likewise.
2003-12-19 Ulrich Drepper <drepper@redhat.com>

View File

@ -65,6 +65,12 @@ pthread_cancel (th)
thread as canceled. */
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_cancel
is not guaranteed to be async-safe. */
int val;
#if __ASSUME_TGKILL
val = INTERNAL_SYSCALL (tgkill, err, 3,

View File

@ -70,7 +70,7 @@ pthread_getattr_np (thread_id, attr)
{
/* No stack information available. This must be for the initial
thread. Get the info in some magical way. */
assert (thread->pid == thread->tid);
assert (abs (thread->pid) == thread->tid);
/* Defined in ld.so. */
extern void *__libc_stack_end;

View File

@ -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 ();

View File

@ -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)

View File

@ -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

View File

@ -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),

View File

@ -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