Update.
authorUlrich Drepper <drepper@redhat.com>
Sat, 10 Jun 2000 08:28:06 +0000 (08:28 +0000)
committerUlrich Drepper <drepper@redhat.com>
Sat, 10 Jun 2000 08:28:06 +0000 (08:28 +0000)
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.

linuxthreads/ChangeLog
linuxthreads/sysdeps/pthread/posix-timer.h
linuxthreads/sysdeps/pthread/timer_create.c
linuxthreads/sysdeps/pthread/timer_routines.c

index 88c866c..f188961 100644 (file)
@@ -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.
index fc56ba6..bb66c2d 100644 (file)
@@ -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);
index d6d756d..cbefb91 100644 (file)
@@ -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))
index a5f2561..42c0131 100644 (file)
@@ -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;