diff --git a/nptl/ChangeLog b/nptl/ChangeLog index e0e2beeb92..1fda8e4178 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,3 +1,16 @@ +2003-12-23 Jakub Jelinek + + * sysdeps/unix/sysv/linux/raise.c (raise): Protect pid = selftid + setting with __ASSUME_TGKILL || defined __NR_tgkill. + If pid is 0, set it to selftid. + * sysdeps/unix/sysv/linux/getpid.c (really_getpid): Make inline. + Don't set self->pid but self->tid. If self->pid == 0 and self->tid + != 0, return self->tid without doing a syscall. + * descr.h (struct pthread): Move pid field after tid. + + * Makefile (tests): Add tst-raise1. + * tst-raise1.c: New file. + 2003-12-23 Roland McGrath * tst-oddstacklimit.c: New file. diff --git a/nptl/Makefile b/nptl/Makefile index 4cacbd6057..08ed1487a5 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -205,6 +205,7 @@ tests = tst-attr1 tst-attr2 tst-attr3 \ tst-align \ tst-basic1 tst-basic2 tst-basic3 tst-basic4 tst-basic5 tst-basic6 \ tst-kill1 tst-kill2 tst-kill3 tst-kill4 tst-kill5 tst-kill6 \ + tst-raise1 \ tst-join1 tst-join2 tst-join3 tst-join4 tst-join5 \ tst-detach1 \ tst-eintr1 tst-eintr2 tst-eintr3 tst-eintr4 tst-eintr5 \ diff --git a/nptl/descr.h b/nptl/descr.h index 6c7f2317c9..a6e35ba3db 100644 --- a/nptl/descr.h +++ b/nptl/descr.h @@ -121,6 +121,9 @@ struct pthread therefore stack) used' flag. */ pid_t tid; + /* Process ID - thread group ID in kernel speak. */ + pid_t pid; + /* List of cleanup buffers. */ struct _pthread_cleanup_buffer *cleanup; @@ -178,9 +181,6 @@ struct pthread /* Two-level array for the thread-specific data. */ struct pthread_key_data *specific[PTHREAD_KEY_1STLEVEL_SIZE]; - /* Process ID - thread group ID in kernel speak. */ - pid_t pid; - /* True if events must be reported. */ bool report_events; diff --git a/nptl/sysdeps/unix/sysv/linux/getpid.c b/nptl/sysdeps/unix/sysv/linux/getpid.c index 7efe3f2768..1c3532b7e1 100644 --- a/nptl/sysdeps/unix/sysv/linux/getpid.c +++ b/nptl/sysdeps/unix/sysv/linux/getpid.c @@ -23,32 +23,42 @@ #ifndef NOT_IN_libc -static pid_t really_getpid (pid_t oldval); -#endif - +static inline __attribute__((always_inline)) pid_t really_getpid (pid_t oldval); -pid_t -__getpid (void) +static inline __attribute__((always_inline)) pid_t +really_getpid (pid_t oldval) { -#ifndef NOT_IN_libc - pid_t result = THREAD_GETMEM (THREAD_SELF, pid); - if (__builtin_expect (result <= 0, 0)) - result = really_getpid (result); + pid_t selftid; + if (__builtin_expect (oldval == 0 + && ((selftid = THREAD_GETMEM (THREAD_SELF, tid)) + != 0), 1)) + return selftid; + + INTERNAL_SYSCALL_DECL (err); + pid_t result = INTERNAL_SYSCALL (getpid, err, 0); + + /* 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. */ + if (oldval == 0) + THREAD_SETMEM (THREAD_SELF, tid, result); return result; } +#endif -static pid_t -really_getpid (pid_t oldval) +pid_t +__getpid (void) { -#endif +#ifdef NOT_IN_libc INTERNAL_SYSCALL_DECL (err); pid_t result = INTERNAL_SYSCALL (getpid, err, 0); -#ifndef NOT_IN_libc - if (oldval == 0) - THREAD_SETMEM (THREAD_SELF, pid, result); +#else + pid_t result = THREAD_GETMEM (THREAD_SELF, pid); + if (__builtin_expect (result <= 0, 0)) + result = really_getpid (result); #endif return result; } + libc_hidden_def (__getpid) weak_alias (__getpid, getpid) libc_hidden_def (getpid) diff --git a/nptl/sysdeps/unix/sysv/linux/raise.c b/nptl/sysdeps/unix/sysv/linux/raise.c index 268ba87b29..ac54fa217e 100644 --- a/nptl/sysdeps/unix/sysv/linux/raise.c +++ b/nptl/sysdeps/unix/sysv/linux/raise.c @@ -44,17 +44,19 @@ raise (sig) #endif THREAD_SETMEM (pd, tid, selftid); +#if __ASSUME_TGKILL || defined __NR_tgkill /* 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; +#endif } #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; + if (__builtin_expect (pid <= 0, 0)) + pid = pid == 0 ? selftid : -pid; #endif #if __ASSUME_TGKILL diff --git a/nptl/tst-raise1.c b/nptl/tst-raise1.c new file mode 100644 index 0000000000..9c291e6c1f --- /dev/null +++ b/nptl/tst-raise1.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include + +volatile int count; + +void +sh (int sig) +{ + ++count; +} + +int +main (void) +{ + struct sigaction sa; + sa.sa_handler = sh; + sigemptyset (&sa.sa_mask); + sa.sa_flags = 0; + if (sigaction (SIGUSR1, &sa, NULL) < 0) + { + printf ("sigaction failed: %m\n"); + exit (1); + } + if (raise (SIGUSR1) < 0) + { + printf ("first raise failed: %m\n"); + exit (1); + } + if (raise (SIGUSR1) < 0) + { + printf ("second raise failed: %m\n"); + exit (1); + } + if (count != 2) + { + printf ("signal handler not called 2 times\n"); + exit (1); + } + exit (0); +}