jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

200 lines
6.5KB

  1. /*
  2. Copyright (C) 2004-2008 Grame
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU Lesser General Public License as published by
  5. the Free Software Foundation; either version 2.1 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. #include "JackPosixProcessSync.h"
  16. #include "JackError.h"
  17. #include "JackPosixCommon.h"
  18. namespace Jack
  19. {
  20. void JackPosixProcessSync::Signal()
  21. {
  22. int res = pthread_cond_signal(&fCond);
  23. if (res != 0) {
  24. jack_error("JackPosixProcessSync::Signal error err = %s", strerror(res));
  25. }
  26. }
  27. // TO DO : check thread consistency?
  28. void JackPosixProcessSync::LockedSignal()
  29. {
  30. int res = pthread_mutex_lock(&fMutex);
  31. if (res != 0) {
  32. jack_error("JackPosixProcessSync::LockedSignal error err = %s", strerror(res));
  33. }
  34. res = pthread_cond_signal(&fCond);
  35. if (res != 0) {
  36. jack_error("JackPosixProcessSync::LockedSignal error err = %s", strerror(res));
  37. }
  38. res = pthread_mutex_unlock(&fMutex);
  39. if (res != 0) {
  40. jack_error("JackPosixProcessSync::LockedSignal error err = %s", strerror(res));
  41. }
  42. }
  43. void JackPosixProcessSync::SignalAll()
  44. {
  45. int res = pthread_cond_broadcast(&fCond);
  46. if (res != 0) {
  47. jack_error("JackPosixProcessSync::SignalAll error err = %s", strerror(res));
  48. }
  49. }
  50. // TO DO : check thread consistency?
  51. void JackPosixProcessSync::LockedSignalAll()
  52. {
  53. int res = pthread_mutex_lock(&fMutex);
  54. if (res != 0) {
  55. jack_error("JackPosixProcessSync::LockedSignalAll error err = %s", strerror(res));
  56. }
  57. res = pthread_cond_broadcast(&fCond);
  58. if (res != 0) {
  59. jack_error("JackPosixProcessSync::LockedSignalAll error err = %s", strerror(res));
  60. }
  61. res = pthread_mutex_unlock(&fMutex);
  62. if (res != 0) {
  63. jack_error("JackPosixProcessSync::LockedSignalAll error err = %s", strerror(res));
  64. }
  65. }
  66. void JackPosixProcessSync::Wait()
  67. {
  68. ThrowIf(!pthread_equal(pthread_self(), fOwner), JackException("JackPosixProcessSync::Wait: a thread has to have locked a mutex before it can wait"));
  69. fOwner = 0;
  70. int res = pthread_cond_wait(&fCond, &fMutex);
  71. if (res != 0) {
  72. jack_error("JackPosixProcessSync::Wait error err = %s", strerror(res));
  73. } else {
  74. fOwner = pthread_self();
  75. }
  76. }
  77. // TO DO : check thread consistency?
  78. void JackPosixProcessSync::LockedWait()
  79. {
  80. int res;
  81. res = pthread_mutex_lock(&fMutex);
  82. if (res != 0) {
  83. jack_error("JackPosixProcessSync::LockedWait error err = %s", strerror(res));
  84. }
  85. if ((res = pthread_cond_wait(&fCond, &fMutex)) != 0) {
  86. jack_error("JackPosixProcessSync::LockedWait error err = %s", strerror(res));
  87. }
  88. res = pthread_mutex_unlock(&fMutex);
  89. if (res != 0) {
  90. jack_error("JackPosixProcessSync::LockedWait error err = %s", strerror(res));
  91. }
  92. }
  93. // TO DO : check thread consistency?
  94. bool JackPosixProcessSync::LockedTimedWait(long usec)
  95. {
  96. int res1, res2, res3;
  97. struct timespec rel_timeout, now_mono, end_mono, now_real, end_real;
  98. struct timespec diff_mono, final_time;
  99. int old_errno;
  100. bool mono_available = true;
  101. double delta;
  102. res1 = pthread_mutex_lock(&fMutex);
  103. if (res1 != 0) {
  104. jack_error("JackPosixProcessSync::LockedTimedWait error err = %s",
  105. usec, strerror(res1));
  106. }
  107. jack_log("JackPosixProcessSync::LockedTimedWait time out = %ld", usec);
  108. /* Convert usec argument to timespec */
  109. rel_timeout.tv_sec = usec / 1000000;
  110. rel_timeout.tv_nsec = (usec % 1000000) * 1000;
  111. /* Calculate absolute monotonic timeout */
  112. res3 = clock_gettime(CLOCK_MONOTONIC, &now_mono);
  113. if (res3 != 0) {
  114. mono_available = false;
  115. }
  116. JackPosixTools::TimespecAdd(&now_mono, &rel_timeout, &end_mono);
  117. /* pthread_cond_timedwait() is affected by abrupt time jumps, i.e. when the
  118. * system time is changed. To protect against this, measure the time
  119. * difference between and after the sem_timedwait() call and if it suggests
  120. * that there has been a time jump, restart the call. */
  121. if (mono_available) {
  122. for (;;) {
  123. /* Calculate absolute realtime timeout, assuming no steps */
  124. res3 = clock_gettime(CLOCK_REALTIME, &now_real);
  125. assert(res3 == 0);
  126. JackPosixTools::TimespecSub(&end_mono, &now_mono, &diff_mono);
  127. JackPosixTools::TimespecAdd(&now_real, &diff_mono, &end_real);
  128. res2 = pthread_cond_timedwait(&fCond, &fMutex, &end_real);
  129. if (res2 != ETIMEDOUT) {
  130. break;
  131. }
  132. /* Compare with monotonic timeout, in case a step happened */
  133. old_errno = errno;
  134. res3 = clock_gettime(CLOCK_MONOTONIC, &now_mono);
  135. assert(res3 == 0);
  136. errno = old_errno;
  137. if (JackPosixTools::TimespecCmp(&now_mono, &end_mono) >= 0) {
  138. break;
  139. }
  140. }
  141. } else {
  142. /* CLOCK_MONOTONIC is not supported, do not check for time skips. */
  143. res3 = clock_gettime(CLOCK_REALTIME, &now_real);
  144. assert(res3 == 0);
  145. JackPosixTools::TimespecAdd(&now_real, &rel_timeout, &end_real);
  146. res2 = pthread_cond_timedwait(&fCond, &fMutex, &end_real);
  147. }
  148. res1 = pthread_mutex_unlock(&fMutex);
  149. if (res1 != 0) {
  150. jack_error("JackPosixProcessSync::LockedTimedWait error err = %s",
  151. strerror(res1));
  152. }
  153. if (res2 != 0) {
  154. jack_error("JackPosixProcessSync::LockedTimedWait error usec = %ld err = %s",
  155. usec, strerror(res2));
  156. }
  157. old_errno = errno;
  158. if (mono_available) {
  159. res3 = clock_gettime(CLOCK_MONOTONIC, &final_time);
  160. assert(res3 == 0);
  161. delta = 1e6 * final_time.tv_sec - 1e6 * now_mono.tv_sec +
  162. (final_time.tv_nsec - now_mono.tv_nsec) / 1000;
  163. } else {
  164. res3 = clock_gettime(CLOCK_REALTIME, &final_time);
  165. assert(res3 == 0);
  166. delta = 1e6 * final_time.tv_sec - 1e6 * now_real.tv_sec +
  167. (final_time.tv_nsec - now_real.tv_nsec) / 1000;
  168. }
  169. errno = old_errno;
  170. jack_log("JackPosixProcessSync::LockedTimedWait finished delta = %5.1lf", delta);
  171. return res2 == 0;
  172. }
  173. } // end of namespace