aboutsummaryrefslogtreecommitdiff
path: root/linuxthreads
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2000-06-10 08:28:06 +0000
committerUlrich Drepper <drepper@redhat.com>2000-06-10 08:28:06 +0000
commit45dc1187ee47bc0ffa9bb7ff7ac49749aaabe413 (patch)
tree79f3540143b070f52eb00aa78d7abf00fd0aa772 /linuxthreads
parent15109bd4aa7cef49d08ba0c3939b5389a3b90803 (diff)
downloadglibc-45dc1187ee47bc0ffa9bb7ff7ac49749aaabe413.tar
glibc-45dc1187ee47bc0ffa9bb7ff7ac49749aaabe413.tar.gz
glibc-45dc1187ee47bc0ffa9bb7ff7ac49749aaabe413.tar.bz2
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.
Diffstat (limited to 'linuxthreads')
-rw-r--r--linuxthreads/ChangeLog15
-rw-r--r--linuxthreads/sysdeps/pthread/posix-timer.h19
-rw-r--r--linuxthreads/sysdeps/pthread/timer_create.c27
-rw-r--r--linuxthreads/sysdeps/pthread/timer_routines.c69
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;