From 0ecb606cb6cf65de1d9fc8a919bceb4be476c602 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 12 Jul 2007 18:26:36 +0000 Subject: 2.5-18.1 --- nptl/sysdeps/unix/sysv/linux/timer_routines.c | 50 ++++++++++++++++++++------- 1 file changed, 37 insertions(+), 13 deletions(-) (limited to 'nptl/sysdeps/unix/sysv/linux/timer_routines.c') diff --git a/nptl/sysdeps/unix/sysv/linux/timer_routines.c b/nptl/sysdeps/unix/sysv/linux/timer_routines.c index 23c800f98e..a5eb442251 100644 --- a/nptl/sysdeps/unix/sysv/linux/timer_routines.c +++ b/nptl/sysdeps/unix/sysv/linux/timer_routines.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2003. @@ -27,6 +27,13 @@ #include "kernel-posix-timers.h" +struct thread_start_data +{ + void (*thrfunc) (sigval_t); + sigval_t sival; +}; + + #ifdef __NR_timer_create /* Helper thread to call the user-provided function. */ static void * @@ -40,10 +47,16 @@ timer_sigev_thread (void *arg) INTERNAL_SYSCALL_DECL (err); INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, NULL, _NSIG / 8); - struct timer *tk = (struct timer *) arg; + struct thread_start_data *td = (struct thread_start_data *) arg; + + void (*thrfunc) (sigval_t) = td->thrfunc; + sigval_t sival = td->sival; + + /* The TD object was allocated in timer_helper_thread. */ + free (td); /* Call the user-provided function. */ - tk->thrfunc (tk->sival); + thrfunc (sival); return NULL; } @@ -53,10 +66,11 @@ timer_sigev_thread (void *arg) static void * timer_helper_thread (void *arg) { - /* Wait for the SIGTIMER signal and none else. */ + /* Wait for the SIGTIMER signal, allowing the setXid signal, and + none else. */ sigset_t ss; sigemptyset (&ss); - sigaddset (&ss, SIGTIMER); + __sigaddset (&ss, SIGTIMER); /* Endless loop of waiting for signals. The loop is only ended when the thread is canceled. */ @@ -81,10 +95,19 @@ timer_helper_thread (void *arg) if (si.si_code == SI_TIMER) { struct timer *tk = (struct timer *) si.si_ptr; - - /* That the signal we are waiting for. */ - pthread_t th; - (void) pthread_create (&th, &tk->attr, timer_sigev_thread, tk); + struct thread_start_data *td = malloc (sizeof (*td)); + + /* There is not much we can do if the allocation fails. */ + if (td != NULL) + { + /* That is the signal we are waiting for. */ + td->thrfunc = tk->thrfunc; + td->sival = tk->sival; + + pthread_t th; + (void) pthread_create (&th, &tk->attr, timer_sigev_thread, + td); + } } else if (si.si_code == SI_TKILL) /* The thread is canceled. */ @@ -121,10 +144,11 @@ __start_helper_thread (void) (void) pthread_attr_init (&attr); (void) pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN); - /* Block all signals in the helper thread. To do this thoroughly we - temporarily have to block all signals here. The helper can lose - wakeups if SIGCANCEL is not blocked throughout, but sigfillset omits - it. So, we add it back explicitly here. */ + /* Block all signals in the helper thread but SIGSETXID. To do this + thoroughly we temporarily have to block all signals here. The + helper can lose wakeups if SIGCANCEL is not blocked throughout, + but sigfillset omits it SIGSETXID. So, we add SIGCANCEL back + explicitly here. */ sigset_t ss; sigset_t oss; sigfillset (&ss); -- cgit 1.4.1