From f160a450c930f214f218f0c975abf188d367716f Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Sun, 28 Oct 2007 19:46:50 +0000 Subject: [PATCH] [BZ #5204] * crypt/sha256c-test.c: Define TIMEOUT to 6 for ancient hardware. * crypt/sha512c-test.c: Likewise. --- ChangeLog | 4 ++ crypt/sha256c-test.c | 1 + crypt/sha512c-test.c | 1 + nptl/ChangeLog | 16 +++++++ .../unix/sysv/linux/kernel-posix-timers.h | 10 ++++- nptl/sysdeps/unix/sysv/linux/timer_create.c | 7 +++ nptl/sysdeps/unix/sysv/linux/timer_delete.c | 23 +++++++++- nptl/sysdeps/unix/sysv/linux/timer_routines.c | 45 ++++++++++++++----- 8 files changed, 94 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index b59939f91d..257cc320d5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2007-10-28 Ulrich Drepper + [BZ #5204] + * crypt/sha256c-test.c: Define TIMEOUT to 6 for ancient hardware. + * crypt/sha512c-test.c: Likewise. + [BZ #5225] * stdio-common/vfscanf.c (_IO_vfwscanf): Don't misuse wp pointer to keep track of end of %[ format string element. diff --git a/crypt/sha256c-test.c b/crypt/sha256c-test.c index 58aec07dae..357f0d8b7e 100644 --- a/crypt/sha256c-test.c +++ b/crypt/sha256c-test.c @@ -57,5 +57,6 @@ do_test (void) return result; } +#define TIMEOUT 6 #define TEST_FUNCTION do_test () #include "../test-skeleton.c" diff --git a/crypt/sha512c-test.c b/crypt/sha512c-test.c index 4c888feb41..c829242e2a 100644 --- a/crypt/sha512c-test.c +++ b/crypt/sha512c-test.c @@ -58,5 +58,6 @@ do_test (void) return result; } +#define TIMEOUT 6 #define TEST_FUNCTION do_test () #include "../test-skeleton.c" diff --git a/nptl/ChangeLog b/nptl/ChangeLog index 5eabd538bc..6ea079a1b2 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,3 +1,19 @@ +2007-10-28 Ulrich Drepper + + [BZ #5220] + * sysdeps/unix/sysv/linux/kernel-posix-timers.h: Declare + __active_timer_sigev_thread and __active_timer_sigev_thread_lock. + (struct timer): Add next element. + * sysdeps/unix/sysv/linux/timer_create.c: For SIGEV_THREAD timers, + enqueue timer structure into __active_timer_sigev_thread list. + * sysdeps/unix/sysv/linux/timer_delete.c: For SIGEV_THREAD timers, + remove timer struct from __active_timer_sigev_thread. + * sysdeps/unix/sysv/linux/timer_routines.c (timer_helper_thread): + Before using timer structure make sure it is still on the + __active_timer_sigev_thread list. Keep lock until done. + Define __active_timer_sigev_thread and + __active_timer_sigev_thread_lock. + 2007-10-27 Ulrich Drepper * sysdeps/pthread/malloc-machine.h: Define ATFORK_MEM. diff --git a/nptl/sysdeps/unix/sysv/linux/kernel-posix-timers.h b/nptl/sysdeps/unix/sysv/linux/kernel-posix-timers.h index 3ff4cda3f4..5f419c2144 100644 --- a/nptl/sysdeps/unix/sysv/linux/kernel-posix-timers.h +++ b/nptl/sysdeps/unix/sysv/linux/kernel-posix-timers.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2003. @@ -35,6 +35,11 @@ extern pthread_once_t __helper_once attribute_hidden; /* TID of the helper thread. */ extern pid_t __helper_tid attribute_hidden; +/* List of active SIGEV_THREAD timers. */ +extern struct timer *__active_timer_sigev_thread attribute_hidden; +/* Lock for the __active_timer_sigev_thread. */ +extern pthread_mutex_t __active_timer_sigev_thread_lock attribute_hidden; + /* Type of timers in the kernel. */ typedef int kernel_timer_t; @@ -57,4 +62,7 @@ struct timer void (*thrfunc) (sigval_t); sigval_t sival; pthread_attr_t attr; + + /* Next element in list of active SIGEV_THREAD timers. */ + struct timer *next; }; diff --git a/nptl/sysdeps/unix/sysv/linux/timer_create.c b/nptl/sysdeps/unix/sysv/linux/timer_create.c index 497068b554..a07234d7d1 100644 --- a/nptl/sysdeps/unix/sysv/linux/timer_create.c +++ b/nptl/sysdeps/unix/sysv/linux/timer_create.c @@ -206,6 +206,13 @@ timer_create (clock_id, evp, timerid) syscall_clockid, &sev, &newp->ktimerid); if (! INTERNAL_SYSCALL_ERROR_P (res, err)) { + /* Add to the queue of active timers with thread + delivery. */ + pthread_mutex_lock (&__active_timer_sigev_thread_lock); + newp->next = __active_timer_sigev_thread; + __active_timer_sigev_thread = newp; + pthread_mutex_unlock (&__active_timer_sigev_thread_lock); + *timerid = (timer_t) newp; return 0; } diff --git a/nptl/sysdeps/unix/sysv/linux/timer_delete.c b/nptl/sysdeps/unix/sysv/linux/timer_delete.c index 35055212a3..510541fc2a 100644 --- a/nptl/sysdeps/unix/sysv/linux/timer_delete.c +++ b/nptl/sysdeps/unix/sysv/linux/timer_delete.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2003. @@ -54,6 +54,27 @@ timer_delete (timerid) if (res == 0) { + if (kt->sigev_notify == SIGEV_THREAD) + { + /* Remove the timer from the list. */ + pthread_mutex_lock (&__active_timer_sigev_thread_lock); + if (__active_timer_sigev_thread == kt) + __active_timer_sigev_thread = kt->next; + else + { + struct timer *prevp = __active_timer_sigev_thread; + while (prevp->next != NULL) + if (prevp->next == kt) + { + prevp->next = kt->next; + break; + } + else + prevp = prevp->next; + } + pthread_mutex_unlock (&__active_timer_sigev_thread_lock); + } + # ifndef __ASSUME_POSIX_TIMERS /* We know the syscall support is available. */ __no_posix_timers = 1; diff --git a/nptl/sysdeps/unix/sysv/linux/timer_routines.c b/nptl/sysdeps/unix/sysv/linux/timer_routines.c index a5eb442251..b159316fb2 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, 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2003. @@ -27,6 +27,12 @@ #include "kernel-posix-timers.h" +/* List of active SIGEV_THREAD timers. */ +struct timer *__active_timer_sigev_thread; +/* Lock for the __active_timer_sigev_thread. */ +pthread_mutex_t __active_timer_sigev_thread_lock = PTHREAD_MUTEX_INITIALIZER; + + struct thread_start_data { void (*thrfunc) (sigval_t); @@ -95,19 +101,36 @@ timer_helper_thread (void *arg) if (si.si_code == SI_TIMER) { struct timer *tk = (struct timer *) si.si_ptr; - 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; + /* Check the timer is still used and will not go away + while we are reading the values here. */ + pthread_mutex_lock (&__active_timer_sigev_thread_lock); - pthread_t th; - (void) pthread_create (&th, &tk->attr, timer_sigev_thread, - td); + struct timer *runp = __active_timer_sigev_thread; + while (runp != NULL) + if (runp == tk) + break; + else + runp = runp->next; + + if (runp != NULL) + { + struct thread_start_data *td = malloc (sizeof (*td)); + + /* There is not much we can do if the allocation fails. */ + if (td != NULL) + { + /* This 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); + } } + + pthread_mutex_unlock (&__active_timer_sigev_thread_lock); } else if (si.si_code == SI_TKILL) /* The thread is canceled. */