timer_create.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /* Copyright (C) 2000, 2003, 2004 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. Contributed by Kaz Kylheku <kaz@ashi.footprints.net>.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public License as
  6. published by the Free Software Foundation; either version 2.1 of the
  7. License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; see the file COPYING.LIB. If not,
  14. write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  15. Boston, MA 02111-1307, USA. */
  16. #include <errno.h>
  17. #include <signal.h>
  18. #include <pthread.h>
  19. #include <time.h>
  20. #include <unistd.h>
  21. #include "posix-timer.h"
  22. /* Create new per-process timer using CLOCK. */
  23. int
  24. timer_create (
  25. clockid_t clock_id,
  26. struct sigevent *evp,
  27. timer_t *timerid)
  28. {
  29. int retval = -1;
  30. struct timer_node *newtimer = NULL;
  31. struct thread_node *thread = NULL;
  32. if (0
  33. #if defined _POSIX_CPUTIME && _POSIX_CPUTIME >= 0
  34. || clock_id == CLOCK_PROCESS_CPUTIME_ID
  35. #endif
  36. #if defined _POSIX_THREAD_CPUTIME && _POSIX_THREAD_CPUTIME >= 0
  37. || clock_id == CLOCK_THREAD_CPUTIME_ID
  38. #endif
  39. )
  40. {
  41. /* We don't allow timers for CPU clocks. At least not in the
  42. moment. */
  43. __set_errno (ENOTSUP);
  44. return -1;
  45. }
  46. if (clock_id != CLOCK_REALTIME)
  47. {
  48. __set_errno (EINVAL);
  49. return -1;
  50. }
  51. pthread_once (&__timer_init_once_control, __timer_init_once);
  52. if (__timer_init_failed)
  53. {
  54. __set_errno (ENOMEM);
  55. return -1;
  56. }
  57. pthread_mutex_lock (&__timer_mutex);
  58. newtimer = __timer_alloc ();
  59. if (__builtin_expect (newtimer == NULL, 0))
  60. {
  61. __set_errno (EAGAIN);
  62. goto unlock_bail;
  63. }
  64. if (evp != NULL)
  65. newtimer->event = *evp;
  66. else
  67. {
  68. newtimer->event.sigev_notify = SIGEV_SIGNAL;
  69. newtimer->event.sigev_signo = SIGALRM;
  70. newtimer->event.sigev_value.sival_ptr = timer_ptr2id (newtimer);
  71. newtimer->event.sigev_notify_function = 0;
  72. }
  73. newtimer->event.sigev_notify_attributes = &newtimer->attr;
  74. newtimer->creator_pid = getpid ();
  75. switch (__builtin_expect (newtimer->event.sigev_notify, SIGEV_SIGNAL))
  76. {
  77. case SIGEV_NONE:
  78. case SIGEV_SIGNAL:
  79. /* We have a global thread for delivering timed signals.
  80. If it is not running, try to start it up. */
  81. thread = &__timer_signal_thread_rclk;
  82. if (! thread->exists)
  83. {
  84. if (__builtin_expect (__timer_thread_start (thread),
  85. 1) < 0)
  86. {
  87. __set_errno (EAGAIN);
  88. goto unlock_bail;
  89. }
  90. }
  91. break;
  92. case SIGEV_THREAD:
  93. /* Copy over thread attributes or set up default ones. */
  94. if (evp->sigev_notify_attributes)
  95. newtimer->attr = *(pthread_attr_t *) evp->sigev_notify_attributes;
  96. else
  97. pthread_attr_init (&newtimer->attr);
  98. /* Ensure thread attributes call for deatched thread. */
  99. pthread_attr_setdetachstate (&newtimer->attr, PTHREAD_CREATE_DETACHED);
  100. /* Try to find existing thread having the right attributes. */
  101. thread = __timer_thread_find_matching (&newtimer->attr, clock_id);
  102. /* If no existing thread has these attributes, try to allocate one. */
  103. if (thread == NULL)
  104. thread = __timer_thread_alloc (&newtimer->attr, clock_id);
  105. /* Out of luck; no threads are available. */
  106. if (__builtin_expect (thread == NULL, 0))
  107. {
  108. __set_errno (EAGAIN);
  109. goto unlock_bail;
  110. }
  111. /* If the thread is not running already, try to start it. */
  112. if (! thread->exists
  113. && __builtin_expect (! __timer_thread_start (thread), 0))
  114. {
  115. __set_errno (EAGAIN);
  116. goto unlock_bail;
  117. }
  118. break;
  119. default:
  120. __set_errno (EINVAL);
  121. goto unlock_bail;
  122. }
  123. newtimer->clock = clock_id;
  124. newtimer->abstime = 0;
  125. newtimer->armed = 0;
  126. newtimer->thread = thread;
  127. *timerid = timer_ptr2id (newtimer);
  128. retval = 0;
  129. if (__builtin_expect (retval, 0) == -1)
  130. {
  131. unlock_bail:
  132. if (thread != NULL)
  133. __timer_thread_dealloc (thread);
  134. if (newtimer != NULL)
  135. {
  136. timer_delref (newtimer);
  137. __timer_dealloc (newtimer);
  138. }
  139. }
  140. pthread_mutex_unlock (&__timer_mutex);
  141. return retval;
  142. }