posix-timer.h 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  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
  15. not, see <http://www.gnu.org/licenses/>. */
  16. #include <limits.h>
  17. #include <signal.h>
  18. /* Double linked list. */
  19. struct list_links
  20. {
  21. struct list_links *next;
  22. struct list_links *prev;
  23. };
  24. /* Forward declaration. */
  25. struct timer_node;
  26. /* Definitions for an internal thread of the POSIX timer implementation. */
  27. struct thread_node
  28. {
  29. struct list_links links;
  30. pthread_attr_t attr;
  31. pthread_t id;
  32. unsigned int exists;
  33. struct list_links timer_queue;
  34. pthread_cond_t cond;
  35. struct timer_node *current_timer;
  36. pthread_t captured;
  37. clockid_t clock_id;
  38. };
  39. /* Internal representation of a timer. */
  40. struct timer_node
  41. {
  42. struct list_links links;
  43. struct sigevent event;
  44. clockid_t clock;
  45. struct itimerspec value;
  46. struct timespec expirytime;
  47. pthread_attr_t attr;
  48. unsigned int abstime;
  49. unsigned int armed;
  50. enum {
  51. TIMER_FREE, TIMER_INUSE, TIMER_DELETED
  52. } inuse;
  53. struct thread_node *thread;
  54. pid_t creator_pid;
  55. int refcount;
  56. int overrun_count;
  57. };
  58. /* Static array with the structures for all the timers. */
  59. extern struct timer_node __timer_array[TIMER_MAX];
  60. /* Global lock to protect operation on the lists. */
  61. extern pthread_mutex_t __timer_mutex;
  62. /* Variable to protext initialization. */
  63. extern pthread_once_t __timer_init_once_control;
  64. /* Nonzero if initialization of timer implementation failed. */
  65. extern int __timer_init_failed;
  66. /* Nodes for the threads used to deliver signals. */
  67. /* A distinct thread is used for each clock type. */
  68. extern struct thread_node __timer_signal_thread_rclk;
  69. /* Return pointer to timer structure corresponding to ID. */
  70. static __inline__ struct timer_node *
  71. timer_id2ptr (timer_t timerid)
  72. {
  73. if (timerid >= 0 && timerid < TIMER_MAX)
  74. return &__timer_array[timerid];
  75. return NULL;
  76. }
  77. /* Return ID of TIMER. */
  78. static __inline__ int
  79. timer_ptr2id (struct timer_node *timer)
  80. {
  81. return timer - __timer_array;
  82. }
  83. /* Check whether timer is valid; global mutex must be held. */
  84. static __inline__ int
  85. timer_valid (struct timer_node *timer)
  86. {
  87. return timer && timer->inuse == TIMER_INUSE;
  88. }
  89. /* Timer refcount functions; need global mutex. */
  90. extern void __timer_dealloc (struct timer_node *timer);
  91. static __inline__ void
  92. timer_addref (struct timer_node *timer)
  93. {
  94. timer->refcount++;
  95. }
  96. static __inline__ void
  97. timer_delref (struct timer_node *timer)
  98. {
  99. if (--timer->refcount == 0)
  100. __timer_dealloc (timer);
  101. }
  102. /* Timespec helper routines. */
  103. static __inline__ int
  104. timespec_compare (const struct timespec *left, const struct timespec *right)
  105. {
  106. if (left->tv_sec < right->tv_sec)
  107. return -1;
  108. if (left->tv_sec > right->tv_sec)
  109. return 1;
  110. if (left->tv_nsec < right->tv_nsec)
  111. return -1;
  112. if (left->tv_nsec > right->tv_nsec)
  113. return 1;
  114. return 0;
  115. }
  116. static __inline__ void
  117. timespec_add (struct timespec *sum, const struct timespec *left,
  118. const struct timespec *right)
  119. {
  120. sum->tv_sec = left->tv_sec + right->tv_sec;
  121. sum->tv_nsec = left->tv_nsec + right->tv_nsec;
  122. if (sum->tv_nsec >= 1000000000)
  123. {
  124. ++sum->tv_sec;
  125. sum->tv_nsec -= 1000000000;
  126. }
  127. }
  128. static __inline__ void
  129. timespec_sub (struct timespec *diff, const struct timespec *left,
  130. const struct timespec *right)
  131. {
  132. diff->tv_sec = left->tv_sec - right->tv_sec;
  133. diff->tv_nsec = left->tv_nsec - right->tv_nsec;
  134. if (diff->tv_nsec < 0)
  135. {
  136. --diff->tv_sec;
  137. diff->tv_nsec += 1000000000;
  138. }
  139. }
  140. /* We need one of the list functions in the other modules. */
  141. static __inline__ void
  142. list_unlink_ip (struct list_links *list)
  143. {
  144. struct list_links *lnext = list->next, *lprev = list->prev;
  145. lnext->prev = lprev;
  146. lprev->next = lnext;
  147. /* The suffix ip means idempotent; list_unlink_ip can be called
  148. * two or more times on the same node.
  149. */
  150. list->next = list;
  151. list->prev = list;
  152. }
  153. /* Functions in the helper file. */
  154. extern void __timer_mutex_cancel_handler (void *arg);
  155. extern void __timer_init_once (void);
  156. extern struct timer_node *__timer_alloc (void);
  157. extern int __timer_thread_start (struct thread_node *thread);
  158. extern struct thread_node *__timer_thread_find_matching (const pthread_attr_t *desired_attr, clockid_t);
  159. extern struct thread_node *__timer_thread_alloc (const pthread_attr_t *desired_attr, clockid_t);
  160. extern void __timer_thread_dealloc (struct thread_node *thread);
  161. extern int __timer_thread_queue_timer (struct thread_node *thread,
  162. struct timer_node *insert);
  163. extern void __timer_thread_wakeup (struct thread_node *thread);