aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2003-12-27 07:38:25 +0000
committerUlrich Drepper <drepper@redhat.com>2003-12-27 07:38:25 +0000
commitcb5b9388dad6d0524322d45eafaa7b5d7b00b554 (patch)
treed1c543bdfe5bcaa0fb71816104857a9bcbead484
parentdc8527f6475c8dd3682fd9203e91a01c77443463 (diff)
downloadglibc-cb5b9388dad6d0524322d45eafaa7b5d7b00b554.zip
glibc-cb5b9388dad6d0524322d45eafaa7b5d7b00b554.tar.gz
glibc-cb5b9388dad6d0524322d45eafaa7b5d7b00b554.tar.bz2
Update.
2003-12-23 Jakub Jelinek <jakub@redhat.com> * 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.
-rw-r--r--nptl/ChangeLog13
-rw-r--r--nptl/Makefile1
-rw-r--r--nptl/descr.h6
-rw-r--r--nptl/sysdeps/unix/sysv/linux/getpid.c40
-rw-r--r--nptl/sysdeps/unix/sysv/linux/raise.c6
-rw-r--r--nptl/tst-raise1.c42
6 files changed, 88 insertions, 20 deletions
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index e0e2bee..1fda8e4 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,3 +1,16 @@
+2003-12-23 Jakub Jelinek <jakub@redhat.com>
+
+ * 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 <roland@redhat.com>
* tst-oddstacklimit.c: New file.
diff --git a/nptl/Makefile b/nptl/Makefile
index 4cacbd6..08ed148 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 6c7f231..a6e35ba 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 7efe3f2..1c3532b 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 268ba87..ac54fa2 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 0000000..9c291e6
--- /dev/null
+++ b/nptl/tst-raise1.c
@@ -0,0 +1,42 @@
+#include <errno.h>
+#include <error.h>
+#include <signal.h>
+#include <stdlib.h>
+
+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);
+}