posix-timer.h 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /* Definitions for POSIX timer implementation on top of LinuxThreads.
  2. Copyright (C) 2000, 2002, 2004 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. Contributed by Kaz Kylheku <kaz@ashi.footprints.net>.
  5. The GNU C Library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Lesser General Public License as
  7. published by the Free Software Foundation; either version 2.1 of the
  8. License, or (at your option) any later version.
  9. The GNU C Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public
  14. License along with the GNU C Library; see the file COPYING.LIB. If not,
  15. write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  16. Boston, MA 02111-1307, USA. */
  17. #include <limits.h>
  18. #include <signal.h>
  19. /* Double linked list. */
  20. struct list_links
  21. {
  22. struct list_links *next;
  23. struct list_links *prev;
  24. };
  25. /* Forward declaration. */
  26. struct timer_node;
  27. /* Definitions for an internal thread of the POSIX timer implementation. */
  28. struct thread_node
  29. {
  30. struct list_links links;
  31. pthread_attr_t attr;
  32. pthread_t id;
  33. unsigned int exists;
  34. struct list_links timer_queue;
  35. pthread_cond_t cond;
  36. struct timer_node *current_timer;
  37. pthread_t captured;
  38. clockid_t clock_id;
  39. };
  40. /* Internal representation of a timer. */
  41. struct timer_node
  42. {
  43. struct list_links links;
  44. struct sigevent event;
  45. clockid_t clock;
  46. struct itimerspec value;
  47. struct timespec expirytime;
  48. pthread_attr_t attr;
  49. unsigned int abstime;
  50. unsigned int armed;
  51. enum {
  52. TIMER_FREE, TIMER_INUSE, TIMER_DELETED
  53. } inuse;
  54. struct thread_node *thread;
  55. pid_t creator_pid;
  56. int refcount;
  57. int overrun_count;
  58. };
  59. /* Static array with the structures for all the timers. */
  60. extern struct timer_node __timer_array[TIMER_MAX];
  61. /* Global lock to protect operation on the lists. */
  62. extern pthread_mutex_t __timer_mutex;
  63. /* Variable to protext initialization. */
  64. extern pthread_once_t __timer_init_once_control;
  65. /* Nonzero if initialization of timer implementation failed. */
  66. extern int __timer_init_failed;
  67. /* Nodes for the threads used to deliver signals. */
  68. /* A distinct thread is used for each clock type. */
  69. extern struct thread_node __timer_signal_thread_rclk;
  70. /* Return pointer to timer structure corresponding to ID. */
  71. static inline struct timer_node *
  72. timer_id2ptr (timer_t timerid)
  73. {
  74. if (timerid >= 0 && timerid < TIMER_MAX)
  75. return &__timer_array[timerid];
  76. return NULL;
  77. }
  78. /* Return ID of TIMER. */
  79. static inline int
  80. timer_ptr2id (struct timer_node *timer)
  81. {
  82. return timer - __timer_array;
  83. }
  84. /* Check whether timer is valid; global mutex must be held. */
  85. static inline int
  86. timer_valid (struct timer_node *timer)
  87. {
  88. return timer && timer->inuse == TIMER_INUSE;
  89. }
  90. /* Timer refcount functions; need global mutex. */
  91. extern void __timer_dealloc (struct timer_node *timer);
  92. static inline void
  93. timer_addref (struct timer_node *timer)
  94. {
  95. timer->refcount++;
  96. }
  97. static inline void
  98. timer_delref (struct timer_node *timer)
  99. {
  100. if (--timer->refcount == 0)
  101. __timer_dealloc (timer);
  102. }
  103. /* Timespec helper routines. */
  104. static inline int
  105. timespec_compare (const struct timespec *left, const struct timespec *right)
  106. {
  107. if (left->tv_sec < right->tv_sec)
  108. return -1;
  109. if (left->tv_sec > right->tv_sec)
  110. return 1;
  111. if (left->tv_nsec < right->tv_nsec)
  112. return -1;
  113. if (left->tv_nsec > right->tv_nsec)
  114. return 1;
  115. return 0;
  116. }
  117. static inline void
  118. timespec_add (struct timespec *sum, const struct timespec *left,
  119. const struct timespec *right)
  120. {
  121. sum->tv_sec = left->tv_sec + right->tv_sec;
  122. sum->tv_nsec = left->tv_nsec + right->tv_nsec;
  123. if (sum->tv_nsec >= 1000000000)
  124. {
  125. ++sum->tv_sec;
  126. sum->tv_nsec -= 1000000000;
  127. }
  128. }
  129. static inline void
  130. timespec_sub (struct timespec *diff, const struct timespec *left,
  131. const struct timespec *right)
  132. {
  133. diff->tv_sec = left->tv_sec - right->tv_sec;
  134. diff->tv_nsec = left->tv_nsec - right->tv_nsec;
  135. if (diff->tv_nsec < 0)
  136. {
  137. --diff->tv_sec;
  138. diff->tv_nsec += 1000000000;
  139. }
  140. }
  141. /* We need one of the list functions in the other modules. */
  142. static inline void
  143. list_unlink_ip (struct list_links *list)
  144. {
  145. struct list_links *lnext = list->next, *lprev = list->prev;
  146. lnext->prev = lprev;
  147. lprev->next = lnext;
  148. /* The suffix ip means idempotent; list_unlink_ip can be called
  149. * two or more times on the same node.
  150. */
  151. list->next = list;
  152. list->prev = list;
  153. }
  154. /* Functions in the helper file. */
  155. extern void __timer_mutex_cancel_handler (void *arg);
  156. extern void __timer_init_once (void);
  157. extern struct timer_node *__timer_alloc (void);
  158. extern int __timer_thread_start (struct thread_node *thread);
  159. extern struct thread_node *__timer_thread_find_matching (const pthread_attr_t *desired_attr, clockid_t);
  160. extern struct thread_node *__timer_thread_alloc (const pthread_attr_t *desired_attr, clockid_t);
  161. extern void __timer_thread_dealloc (struct thread_node *thread);
  162. extern int __timer_thread_queue_timer (struct thread_node *thread,
  163. struct timer_node *insert);
  164. extern void __timer_thread_wakeup (struct thread_node *thread);