diff options
author | Ulrich Drepper <drepper@redhat.com> | 2000-06-10 08:28:06 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2000-06-10 08:28:06 +0000 |
commit | 45dc1187ee47bc0ffa9bb7ff7ac49749aaabe413 (patch) | |
tree | 79f3540143b070f52eb00aa78d7abf00fd0aa772 | |
parent | 15109bd4aa7cef49d08ba0c3939b5389a3b90803 (diff) | |
download | glibc-45dc1187ee47bc0ffa9bb7ff7ac49749aaabe413.tar.gz glibc-45dc1187ee47bc0ffa9bb7ff7ac49749aaabe413.tar.xz glibc-45dc1187ee47bc0ffa9bb7ff7ac49749aaabe413.zip |
Update.
2000-06-10 Kaz Kylheku <kaz@ashi.footprints.net> * sysdeps/pthread/timer_create.c: Thread matching now done on clock type as well as thread attributes. There are individual global signal-delivering threads for different clock types. * sysdeps/pthread/posix-timer.h: Likewise. * sysdeps/pthread/timer_routines.c: Likewise. * sysdeps/pthread/timer_routines.c: Thread allocation and deallocation function now remembers to put thread on active list and remove from active list. Thus now the feature of binding multiple timers to a single thread actually works.
-rw-r--r-- | linuxthreads/ChangeLog | 15 | ||||
-rw-r--r-- | linuxthreads/sysdeps/pthread/posix-timer.h | 19 | ||||
-rw-r--r-- | linuxthreads/sysdeps/pthread/timer_create.c | 27 | ||||
-rw-r--r-- | linuxthreads/sysdeps/pthread/timer_routines.c | 69 |
4 files changed, 89 insertions, 41 deletions
diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog index 88c866c77f..f188961916 100644 --- a/linuxthreads/ChangeLog +++ b/linuxthreads/ChangeLog @@ -1,3 +1,18 @@ +2000-06-10 Kaz Kylheku <kaz@ashi.footprints.net> + + * sysdeps/pthread/timer_create.c: Thread matching now done on + clock type as well as thread attributes. + There are individual global signal-delivering threads for + different clock types. + * sysdeps/pthread/posix-timer.h: Likewise. + * sysdeps/pthread/timer_routines.c: Likewise. + + * sysdeps/pthread/timer_routines.c: Thread allocation and + deallocation function now remembers to put thread on active + list and remove from active list. + Thus now the feature of binding multiple timers + to a single thread actually works. + 2000-06-10 Ulrich Drepper <drepper@redhat.com> * pthread.c (__pthread_create_2_1): Optimize a bit. diff --git a/linuxthreads/sysdeps/pthread/posix-timer.h b/linuxthreads/sysdeps/pthread/posix-timer.h index fc56ba61aa..bb66c2d3d8 100644 --- a/linuxthreads/sysdeps/pthread/posix-timer.h +++ b/linuxthreads/sysdeps/pthread/posix-timer.h @@ -44,6 +44,7 @@ struct thread_node pthread_cond_t cond; struct timer_node *current_timer; pthread_t captured; + clockid_t clock_id; }; @@ -76,8 +77,16 @@ extern pthread_once_t __timer_init_once_control; /* Nonzero if initialization of timer implementation failed. */ extern int __timer_init_failed; -/* Node for the thread used to deliver signals. */ -extern struct thread_node __timer_signal_thread; +/* Nodes for the threads used to deliver signals. */ +/* A distinct thread is used for each clock type. */ + +extern struct thread_node __timer_signal_thread_rclk; +#ifdef _POSIX_CPUTIME +extern struct thread_node __timer_signal_thread_pclk; +#endif +#ifdef _POSIX_THREAD_CPUTIME +extern struct thread_node __timer_signal_thread_tclk; +#endif /* Return pointer to timer structure corresponding to ID. */ @@ -160,10 +169,10 @@ extern void __timer_mutex_cancel_handler (void *arg); extern void __timer_init_once (void); extern struct timer_node *__timer_alloc (void); extern int __timer_thread_start (struct thread_node *thread); -extern struct thread_node *__timer_thread_find_matching (const pthread_attr_t *desired_attr); -extern struct thread_node *__timer_thread_alloc (const pthread_attr_t *desired_attr); +extern struct thread_node *__timer_thread_find_matching (const pthread_attr_t *desired_attr, clockid_t); +extern struct thread_node *__timer_thread_alloc (const pthread_attr_t *desired_attr, clockid_t); extern void __timer_dealloc (struct timer_node *timer); extern void __timer_thread_dealloc (struct thread_node *thread); -extern int __timer_thread_queue_timer (struct thread_node *thread, +extern void __timer_thread_queue_timer (struct thread_node *thread, struct timer_node *insert); extern void __timer_thread_wakeup (struct thread_node *thread); diff --git a/linuxthreads/sysdeps/pthread/timer_create.c b/linuxthreads/sysdeps/pthread/timer_create.c index d6d756d2a6..cbefb91831 100644 --- a/linuxthreads/sysdeps/pthread/timer_create.c +++ b/linuxthreads/sysdeps/pthread/timer_create.c @@ -89,16 +89,33 @@ timer_create (clock_id, evp, timerid) case SIGEV_SIGNAL: /* We have a global thread for delivering timed signals. If it is not running, try to start it up. */ - if (! __timer_signal_thread.exists) + switch (clock_id) { - if (__builtin_expect (__timer_thread_start (&__timer_signal_thread), + case CLOCK_REALTIME: + default: + thread = &__timer_signal_thread_rclk; + break; +#ifdef _POSIX_CPUTIME + case CLOCK_PROCESS_CPUTIME_ID: + thread = &__timer_signal_thread_pclk; + break; +#endif +#ifdef _POSIX_THREAD_CPUTIME + case CLOCK_THREAD_CPUTIME_ID: + thread = &__timer_signal_thread_tclk; + break; +#endif + } + + if (! thread->exists) + { + if (__builtin_expect (__timer_thread_start (thread), 1) < 0) { errno = EAGAIN; goto unlock_bail; } } - thread = &__timer_signal_thread; break; case SIGEV_THREAD: @@ -112,11 +129,11 @@ timer_create (clock_id, evp, timerid) pthread_attr_setdetachstate (&newtimer->attr, PTHREAD_CREATE_DETACHED); /* Try to find existing thread having the right attributes. */ - thread = __timer_thread_find_matching (&newtimer->attr); + thread = __timer_thread_find_matching (&newtimer->attr, clock_id); /* If no existing thread has these attributes, try to allocate one. */ if (thread == NULL) - thread = __timer_thread_alloc (&newtimer->attr); + thread = __timer_thread_alloc (&newtimer->attr, clock_id); /* Out of luck; no threads are available. */ if (__builtin_expect (thread == NULL, 0)) diff --git a/linuxthreads/sysdeps/pthread/timer_routines.c b/linuxthreads/sysdeps/pthread/timer_routines.c index a5f2561449..42c0131662 100644 --- a/linuxthreads/sysdeps/pthread/timer_routines.c +++ b/linuxthreads/sysdeps/pthread/timer_routines.c @@ -49,7 +49,13 @@ pthread_once_t __timer_init_once_control = PTHREAD_ONCE_INIT; int __timer_init_failed; /* Node for the thread used to deliver signals. */ -struct thread_node __timer_signal_thread; +struct thread_node __timer_signal_thread_rclk; +#ifdef _POSIX_CPUTIME +struct thread_node __timer_signal_thread_pclk; +#endif +#ifdef _POSIX_THREAD_CPUTIME +struct thread_node __timer_signal_thread_tclk; +#endif /* Lists to keep free and used timers and threads. */ struct list_links timer_free_list; @@ -127,7 +133,7 @@ timer_links2ptr (struct list_links *list) /* Initialize a newly allocated thread structure. */ static void -thread_init (struct thread_node *thread, const pthread_attr_t *attr) +thread_init (struct thread_node *thread, const pthread_attr_t *attr, clockid_t clock_id) { if (attr != NULL) thread->attr = *attr; @@ -142,6 +148,7 @@ thread_init (struct thread_node *thread, const pthread_attr_t *attr) pthread_cond_init (&thread->cond, 0); thread->current_timer = 0; thread->captured = pthread_self (); + thread->clock_id = clock_id; } @@ -166,7 +173,13 @@ init_module (void) for (i = 0; i < THREAD_MAXNODES; ++i) list_append (&thread_free_list, &thread_array[i].links); - thread_init (&__timer_signal_thread, 0); + thread_init (&__timer_signal_thread_rclk, 0, CLOCK_REALTIME); +#ifdef _POSIX_CPUTIME + thread_init (&__timer_signal_thread_pclk, 0, CLOCK_PROCESS_CPUTIME_ID); +#endif +#ifdef _POSIX_THREAD_CPUTIME + thread_init (&__timer_signal_thread_tclk, 0, CLOCK_THREAD_CPUTIME_ID); +#endif } @@ -203,9 +216,10 @@ thread_deinit (struct thread_node *thread) /* Allocate a thread structure from the global free list. Global - mutex lock must be held by caller. */ + mutex lock must be held by caller. The thread is moved to + the active list. */ struct thread_node * -__timer_thread_alloc (const pthread_attr_t *desired_attr) +__timer_thread_alloc (const pthread_attr_t *desired_attr, clockid_t clock_id) { struct list_links *node = list_first (&thread_free_list); @@ -213,7 +227,8 @@ __timer_thread_alloc (const pthread_attr_t *desired_attr) { struct thread_node *thread = thread_links2ptr (node); list_unlink (node); - thread_init (thread, desired_attr); + thread_init (thread, desired_attr, clock_id); + list_append (&thread_active_list, node); return thread; } @@ -227,6 +242,7 @@ void __timer_thread_dealloc (struct thread_node *thread) { thread_deinit (thread); + list_unlink (&thread->links); list_append (&thread_free_list, &thread->links); } @@ -247,7 +263,13 @@ thread_cleanup (void *val) struct thread_node *thread = val; /* How did the signal thread get killed? */ - assert (thread != &__timer_signal_thread); + assert (thread != &__timer_signal_thread_rclk); +#ifdef _POSIX_CPUTIME + assert (thread != &__timer_signal_thread_pclk); +#endif +#ifdef _POSIX_THREAD_CPUTIME + assert (thread != &__timer_signal_thread_tclk); +#endif pthread_mutex_lock (&__timer_mutex); @@ -379,7 +401,7 @@ thread_func (void *arg) { timespec_add (&timer->expirytime, &now, &timer->value.it_interval); - (void) __timer_thread_queue_timer (self, timer); + __timer_thread_queue_timer (self, timer); } thread_expire_timer (self, timer); @@ -411,40 +433,23 @@ thread_func (void *arg) /* Enqueue a timer in wakeup order in the thread's timer queue. */ -int +void __timer_thread_queue_timer (struct thread_node *thread, struct timer_node *insert) { struct list_links *iter; - struct list_links *matching = NULL; - struct timer_node *timer = NULL; for (iter = list_first (&thread->timer_queue); iter != list_null (&thread->timer_queue); iter = list_next (iter)) { - timer = timer_links2ptr (iter); + struct timer_node *timer = timer_links2ptr (iter); - if (insert->clock == timer->clock) - { - matching = iter; - if (timespec_compare (&insert->expirytime, &timer->expirytime) < 0) - break; - } - } - - if (timer != NULL && insert->clock != timer->clock) - { - if (matching == NULL) - /* We cannot queue this timer. */ - return -1; - - iter = matching; + if (timespec_compare (&insert->expirytime, &timer->expirytime) < 0) + break; } list_insbefore (iter, &insert->links); - - return 0; } @@ -495,7 +500,8 @@ thread_attr_compare (const pthread_attr_t *left, const pthread_attr_t *right) /* Search the list of active threads and find one which has matching attributes. Global mutex lock must be held by caller. */ struct thread_node * -__timer_thread_find_matching (const pthread_attr_t *desired_attr) +__timer_thread_find_matching (const pthread_attr_t *desired_attr, + clockid_t desired_clock_id) { struct list_links *iter = list_first (&thread_active_list); @@ -503,7 +509,8 @@ __timer_thread_find_matching (const pthread_attr_t *desired_attr) { struct thread_node *candidate = thread_links2ptr (iter); - if (thread_attr_compare (desired_attr, &candidate->attr)) + if (thread_attr_compare (desired_attr, &candidate->attr) + && desired_clock_id == candidate->clock_id) { list_unlink (iter); return candidate; |