Back to index

glibc  2.9
posix-timer.h
Go to the documentation of this file.
00001 /* Definitions for POSIX timer implementation on top of NPTL.
00002    Copyright (C) 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Contributed by Kaz Kylheku <kaz@ashi.footprints.net>.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public License as
00008    published by the Free Software Foundation; either version 2.1 of the
00009    License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; see the file COPYING.LIB.  If not,
00018    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00019    Boston, MA 02111-1307, USA.  */
00020 
00021 #include <limits.h>
00022 #include <signal.h>
00023 
00024 /* Double linked list.  */
00025 struct list_links
00026 {
00027   struct list_links *next;
00028   struct list_links *prev;
00029 };
00030 
00031 
00032 /* Forward declaration.  */
00033 struct timer_node;
00034 
00035 
00036 /* Definitions for an internal thread of the POSIX timer implementation.  */
00037 struct thread_node
00038 {
00039   struct list_links links;
00040   pthread_attr_t attr;
00041   pthread_t id;
00042   unsigned int exists;
00043   struct list_links timer_queue;
00044   pthread_cond_t cond;
00045   struct timer_node *current_timer;
00046   pthread_t captured;
00047   clockid_t clock_id;
00048 };
00049 
00050 
00051 /* Internal representation of a timer.  */
00052 struct timer_node
00053 {
00054   struct list_links links;
00055   struct sigevent event;
00056   clockid_t clock;
00057   struct itimerspec value;
00058   struct timespec expirytime;
00059   pthread_attr_t attr;
00060   unsigned int abstime;
00061   unsigned int armed;
00062   enum {
00063     TIMER_FREE, TIMER_INUSE, TIMER_DELETED
00064   } inuse;
00065   struct thread_node *thread;
00066   pid_t creator_pid;
00067   int refcount;
00068   int overrun_count;
00069 };
00070 
00071 
00072 /* The limit is not published if we are compiled with kernel timer support.
00073    But we still compiled in this implementation with its limit unless built
00074    to require the kernel support.  */
00075 #ifndef TIMER_MAX
00076 # define TIMER_MAX 256
00077 #endif
00078 
00079 /* Static array with the structures for all the timers.  */
00080 extern struct timer_node __timer_array[TIMER_MAX];
00081 
00082 /* Global lock to protect operation on the lists.  */
00083 extern pthread_mutex_t __timer_mutex;
00084 
00085 /* Variable to protext initialization.  */
00086 extern pthread_once_t __timer_init_once_control;
00087 
00088 /* Nonzero if initialization of timer implementation failed.  */
00089 extern int __timer_init_failed;
00090 
00091 /* Node for the thread used to deliver signals.  */
00092 extern struct thread_node __timer_signal_thread_rclk;
00093 
00094 
00095 /* Return pointer to timer structure corresponding to ID.  */
00096 #define timer_id2ptr(timerid) ((struct timer_node *) timerid)
00097 #define timer_ptr2id(timerid) ((void *) timerid)
00098 
00099 /* Check whether timer is valid; global mutex must be held. */
00100 static inline int
00101 timer_valid (struct timer_node *timer)
00102 {
00103   return timer && timer->inuse == TIMER_INUSE;
00104 }
00105 
00106 /* Timer refcount functions; need global mutex. */
00107 extern void __timer_dealloc (struct timer_node *timer);
00108 
00109 static inline void
00110 timer_addref (struct timer_node *timer)
00111 {
00112   timer->refcount++;
00113 }
00114 
00115 static inline void
00116 timer_delref (struct timer_node *timer)
00117 {
00118   if (--timer->refcount == 0)
00119     __timer_dealloc (timer);
00120 }
00121 
00122 /* Timespec helper routines.  */
00123 static inline int
00124 __attribute ((always_inline))
00125 timespec_compare (const struct timespec *left, const struct timespec *right)
00126 {
00127   if (left->tv_sec < right->tv_sec)
00128     return -1;
00129   if (left->tv_sec > right->tv_sec)
00130     return 1;
00131 
00132   if (left->tv_nsec < right->tv_nsec)
00133     return -1;
00134   if (left->tv_nsec > right->tv_nsec)
00135     return 1;
00136 
00137   return 0;
00138 }
00139 
00140 static inline void
00141 timespec_add (struct timespec *sum, const struct timespec *left,
00142              const struct timespec *right)
00143 {
00144   sum->tv_sec = left->tv_sec + right->tv_sec;
00145   sum->tv_nsec = left->tv_nsec + right->tv_nsec;
00146 
00147   if (sum->tv_nsec >= 1000000000)
00148     {
00149       ++sum->tv_sec;
00150       sum->tv_nsec -= 1000000000;
00151     }
00152 }
00153 
00154 static inline void
00155 timespec_sub (struct timespec *diff, const struct timespec *left,
00156              const struct timespec *right)
00157 {
00158   diff->tv_sec = left->tv_sec - right->tv_sec;
00159   diff->tv_nsec = left->tv_nsec - right->tv_nsec;
00160 
00161   if (diff->tv_nsec < 0)
00162     {
00163       --diff->tv_sec;
00164       diff->tv_nsec += 1000000000;
00165     }
00166 }
00167 
00168 
00169 /* We need one of the list functions in the other modules.  */
00170 static inline void
00171 list_unlink_ip (struct list_links *list)
00172 {
00173   struct list_links *lnext = list->next, *lprev = list->prev;
00174 
00175   lnext->prev = lprev;
00176   lprev->next = lnext;
00177 
00178   /* The suffix ip means idempotent; list_unlink_ip can be called
00179    * two or more times on the same node.
00180    */
00181 
00182   list->next = list;
00183   list->prev = list;
00184 }
00185 
00186 
00187 /* Functions in the helper file.  */
00188 extern void __timer_mutex_cancel_handler (void *arg);
00189 extern void __timer_init_once (void);
00190 extern struct timer_node *__timer_alloc (void);
00191 extern int __timer_thread_start (struct thread_node *thread);
00192 extern struct thread_node *__timer_thread_find_matching (const pthread_attr_t *desired_attr, clockid_t);
00193 extern struct thread_node *__timer_thread_alloc (const pthread_attr_t *desired_attr, clockid_t);
00194 extern void __timer_thread_dealloc (struct thread_node *thread);
00195 extern int __timer_thread_queue_timer (struct thread_node *thread,
00196                                    struct timer_node *insert);
00197 extern void __timer_thread_wakeup (struct thread_node *thread);