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 + * 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 +#include #include #include +#include #include +#include +#include #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: