about summary refs log tree commit diff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2000-06-08 20:38:08 +0000
committerUlrich Drepper <drepper@redhat.com>2000-06-08 20:38:08 +0000
commit559382738799bf3bef8d81c2091bd713ec8c1c9e (patch)
tree7657c43ac5a62e8d4c00bfee75ab9b4782758d05
parent2715f28ad4494dcf5da41398a6dbf2e43042620d (diff)
downloadglibc-559382738799bf3bef8d81c2091bd713ec8c1c9e.tar.gz
glibc-559382738799bf3bef8d81c2091bd713ec8c1c9e.tar.xz
glibc-559382738799bf3bef8d81c2091bd713ec8c1c9e.zip
Update.
	* sysdeps/pthread/posix-timer.h (struct timer_node): Add creator_pid.
	* sysdeps/pthread/timer_create.c: Fill in creator_pid.
	* sysdeps/pthread/timer_routines.c (thread_expire_timer): Send signal
	with sigqueueinfo is this system call is available.

	* sysdeps/pthread/timer_create.c (timer_create): Allow
	CLOCK_CPUTIME if _POSIX_CPUTIME is defined.
-rw-r--r--linuxthreads/ChangeLog8
-rw-r--r--linuxthreads/sysdeps/pthread/posix-timer.h1
-rw-r--r--linuxthreads/sysdeps/pthread/timer_create.c7
-rw-r--r--linuxthreads/sysdeps/pthread/timer_routines.c45
4 files changed, 51 insertions, 10 deletions
diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog
index 32a0e9f8b7..9571ef0caf 100644
--- a/linuxthreads/ChangeLog
+++ b/linuxthreads/ChangeLog
@@ -1,5 +1,13 @@
 2000-06-08  Ulrich Drepper  <drepper@redhat.com>
 
+	* sysdeps/pthread/posix-timer.h (struct timer_node): Add creator_pid.
+	* sysdeps/pthread/timer_create.c: Fill in creator_pid.
+	* sysdeps/pthread/timer_routines.c (thread_expire_timer): Send signal
+	with sigqueueinfo is this system call is available.
+
+	* sysdeps/pthread/timer_create.c (timer_create): Allow
+	CLOCK_CPUTIME if _POSIX_CPUTIME is defined.
+
 	* sysdeps/pthread/Makefile: New file.  Add rules to build timer
 	functionality.
 	* sysdeps/unix/sysv/linux/bits/local_lim.h: Add TIMER_MAX.
diff --git a/linuxthreads/sysdeps/pthread/posix-timer.h b/linuxthreads/sysdeps/pthread/posix-timer.h
index fcb61aa733..b10ae736d6 100644
--- a/linuxthreads/sysdeps/pthread/posix-timer.h
+++ b/linuxthreads/sysdeps/pthread/posix-timer.h
@@ -50,6 +50,7 @@ struct thread_node
 /* Internal representation of a timer.  */
 struct timer_node
 {
+  pid_t creator_pid;
   struct list_links links;
   struct sigevent event;
   clockid_t clock;
diff --git a/linuxthreads/sysdeps/pthread/timer_create.c b/linuxthreads/sysdeps/pthread/timer_create.c
index 36823e83b6..84e5cfed2f 100644
--- a/linuxthreads/sysdeps/pthread/timer_create.c
+++ b/linuxthreads/sysdeps/pthread/timer_create.c
@@ -36,7 +36,11 @@ timer_create (clock_id, evp, timerid)
   struct timer_node *newtimer = NULL;
   struct thread_node *thread = NULL;
 
-  if (clock_id != CLOCK_REALTIME)
+  if (clock_id != CLOCK_REALTIME
+#ifdef _POSIX_CPUTIME
+      && clock_id != CLOCK_CPUTIME
+#endif
+      )
     {
       errno = EINVAL;
       return -1;
@@ -70,6 +74,7 @@ timer_create (clock_id, evp, timerid)
     }
 
   newtimer->event.sigev_notify_attributes = &newtimer->attr;
+  newtimer->creator_pid = getpid ();
 
   switch (__builtin_expect (newtimer->event.sigev_notify, SIGEV_SIGNAL))
     {
diff --git a/linuxthreads/sysdeps/pthread/timer_routines.c b/linuxthreads/sysdeps/pthread/timer_routines.c
index eb14643c32..cd99c9f12f 100644
--- a/linuxthreads/sysdeps/pthread/timer_routines.c
+++ b/linuxthreads/sysdeps/pthread/timer_routines.c
@@ -19,9 +19,13 @@
    Boston, MA 02111-1307, USA.  */
 
 #include <assert.h>
+#include <errno.h>
 #include <pthread.h>
 #include <stddef.h>
+#include <sysdep.h>
 #include <time.h>
+#include <unistd.h>
+#include <sys/syscall.h>
 
 #include "posix-timer.h"
 
@@ -53,6 +57,11 @@ struct list_links thread_free_list;
 struct list_links thread_active_list;
 
 
+#ifdef __NR_rt_sigqueueinfo
+extern int __syscall_rt_sigqueueinfo (int, int, siginfo_t *);
+#endif
+
+
 /* List handling functions.  */
 static inline void
 list_init (struct list_links *list)
@@ -222,14 +231,13 @@ __timer_thread_dealloc (struct thread_node *thread)
 }
 
 
-/*
- * Each of our threads which terminates executes this cleanup handler. We never
- * terminate threads ourselves; if a thread gets here it means that the evil
- * application has killed it.  If the thread has timers, these require
- * servicing and so we must hire a replacement thread right away.
- * We must also unblock another thread that may have been waiting for
- * this thread to finish servicing a timer (see timer_delete()).
- */
+/* Each of our threads which terminates executes this cleanup
+   handler. We never terminate threads ourselves; if a thread gets here
+   it means that the evil application has killed it.  If the thread has
+   timers, these require servicing and so we must hire a replacement
+   thread right away.  We must also unblock another thread that may
+   have been waiting for this thread to finish servicing a timer (see
+   timer_delete()).  */
 
 static void
 thread_cleanup (void *val)
@@ -272,18 +280,37 @@ thread_expire_timer (struct thread_node *self, struct timer_node *timer)
 
   pthread_mutex_unlock (&__timer_mutex);
 
-  switch (timer->event.sigev_notify)
+  switch (__builtin_expect (timer->event.sigev_notify, SIGEV_SIGNAL))
     {
     case SIGEV_NONE:
       assert (! "timer_create should never have created such a timer");
       break;
 
     case SIGEV_SIGNAL:
+#ifdef __NR_rt_sigqueueinfo
+      {
+	siginfo_t info;
+
+	/* First, clear the siginfo_t structure, so that we don't pass our
+	   stack content to other tasks.  */
+	memset (&info, 0, sizeof (siginfo_t));
+	/* We must pass the information about the data in a siginfo_t
+           value.  */
+	info.si_signo = timer->event.sigev_signo;
+	info.si_code = SI_TIMER;
+	info.si_pid = timer->creator_pid;
+	info.si_uid = getuid ();
+	info.si_value = timer->event.sigev_value;
+
+	INLINE_SYSCALL (rt_sigqueueinfo, 3, info.si_pid, info.si_signo, &info);
+      }
+#else
       if (pthread_kill (self->captured, timer->event.sigev_signo) != 0)
 	{
 	  if (pthread_kill (self->id, timer->event.sigev_signo) != 0)
 	    abort ();
         }
+#endif
       break;
 
     case SIGEV_THREAD: