pthread_delay_np.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /*
  2. * pthreads_delay_np.c
  3. *
  4. * Description:
  5. * This translation unit implements non-portable thread functions.
  6. *
  7. * --------------------------------------------------------------------------
  8. *
  9. * Pthreads-win32 - POSIX Threads Library for Win32
  10. * Copyright(C) 1998 John E. Bossom
  11. * Copyright(C) 1999,2005 Pthreads-win32 contributors
  12. *
  13. * Contact Email: [email protected]
  14. *
  15. * The current list of contributors is contained
  16. * in the file CONTRIBUTORS included with the source
  17. * code distribution. The list can also be seen at the
  18. * following World Wide Web location:
  19. * http://sources.redhat.com/pthreads-win32/contributors.html
  20. *
  21. * This library is free software; you can redistribute it and/or
  22. * modify it under the terms of the GNU Lesser General Public
  23. * License as published by the Free Software Foundation; either
  24. * version 2 of the License, or (at your option) any later version.
  25. *
  26. * This library is distributed in the hope that it will be useful,
  27. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  28. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  29. * Lesser General Public License for more details.
  30. *
  31. * You should have received a copy of the GNU Lesser General Public
  32. * License along with this library in the file COPYING.LIB;
  33. * if not, write to the Free Software Foundation, Inc.,
  34. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  35. */
  36. #include "pthread.h"
  37. #include "implement.h"
  38. /*
  39. * pthread_delay_np
  40. *
  41. * DESCRIPTION
  42. *
  43. * This routine causes a thread to delay execution for a specific period of time.
  44. * This period ends at the current time plus the specified interval. The routine
  45. * will not return before the end of the period is reached, but may return an
  46. * arbitrary amount of time after the period has gone by. This can be due to
  47. * system load, thread priorities, and system timer granularity.
  48. *
  49. * Specifying an interval of zero (0) seconds and zero (0) nanoseconds is
  50. * allowed and can be used to force the thread to give up the processor or to
  51. * deliver a pending cancelation request.
  52. *
  53. * The timespec structure contains the following two fields:
  54. *
  55. * tv_sec is an integer number of seconds.
  56. * tv_nsec is an integer number of nanoseconds.
  57. *
  58. * Return Values
  59. *
  60. * If an error condition occurs, this routine returns an integer value indicating
  61. * the type of error. Possible return values are as follows:
  62. *
  63. * 0
  64. * Successful completion.
  65. * [EINVAL]
  66. * The value specified by interval is invalid.
  67. *
  68. * Example
  69. *
  70. * The following code segment would wait for 5 and 1/2 seconds
  71. *
  72. * struct timespec tsWait;
  73. * int intRC;
  74. *
  75. * tsWait.tv_sec = 5;
  76. * tsWait.tv_nsec = 500000000L;
  77. * intRC = pthread_delay_np(&tsWait);
  78. */
  79. int
  80. pthread_delay_np (struct timespec *interval)
  81. {
  82. DWORD wait_time;
  83. DWORD secs_in_millisecs;
  84. DWORD millisecs;
  85. DWORD status;
  86. pthread_t self;
  87. ptw32_thread_t * sp;
  88. if (interval == NULL)
  89. {
  90. return EINVAL;
  91. }
  92. if (interval->tv_sec == 0L && interval->tv_nsec == 0L)
  93. {
  94. pthread_testcancel ();
  95. Sleep (0);
  96. pthread_testcancel ();
  97. return (0);
  98. }
  99. /* convert secs to millisecs */
  100. secs_in_millisecs = (DWORD)interval->tv_sec * 1000L;
  101. /* convert nanosecs to millisecs (rounding up) */
  102. millisecs = (interval->tv_nsec + 999999L) / 1000000L;
  103. #if defined(__WATCOMC__)
  104. #pragma disable_message (124)
  105. #endif
  106. /*
  107. * Most compilers will issue a warning 'comparison always 0'
  108. * because the variable type is unsigned, but we need to keep this
  109. * for some reason I can't recall now.
  110. */
  111. if (0 > (wait_time = secs_in_millisecs + millisecs))
  112. {
  113. return EINVAL;
  114. }
  115. #if defined(__WATCOMC__)
  116. #pragma enable_message (124)
  117. #endif
  118. if (NULL == (self = pthread_self ()).p)
  119. {
  120. return ENOMEM;
  121. }
  122. sp = (ptw32_thread_t *) self.p;
  123. if (sp->cancelState == PTHREAD_CANCEL_ENABLE)
  124. {
  125. /*
  126. * Async cancelation won't catch us until wait_time is up.
  127. * Deferred cancelation will cancel us immediately.
  128. */
  129. if (WAIT_OBJECT_0 ==
  130. (status = WaitForSingleObject (sp->cancelEvent, wait_time)))
  131. {
  132. ptw32_mcs_local_node_t stateLock;
  133. /*
  134. * Canceling!
  135. */
  136. ptw32_mcs_lock_acquire (&sp->stateLock, &stateLock);
  137. if (sp->state < PThreadStateCanceling)
  138. {
  139. sp->state = PThreadStateCanceling;
  140. sp->cancelState = PTHREAD_CANCEL_DISABLE;
  141. ptw32_mcs_lock_release (&stateLock);
  142. ptw32_throw (PTW32_EPS_CANCEL);
  143. }
  144. ptw32_mcs_lock_release (&stateLock);
  145. return ESRCH;
  146. }
  147. else if (status != WAIT_TIMEOUT)
  148. {
  149. return EINVAL;
  150. }
  151. }
  152. else
  153. {
  154. Sleep (wait_time);
  155. }
  156. return (0);
  157. }