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.

209 lines
5.6KB

  1. /*
  2. Copyright (C) 2001 Paul Davis
  3. Copyright (C) 2004-2006 Grame
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program 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
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. */
  16. #include "JackPosixThread.h"
  17. #include "JackError.h"
  18. #include <string.h> // for memset
  19. namespace Jack
  20. {
  21. void* JackPosixThread::ThreadHandler(void* arg)
  22. {
  23. JackPosixThread* obj = (JackPosixThread*)arg;
  24. JackRunnableInterface* runnable = obj->fRunnable;
  25. int err;
  26. if ((err = pthread_setcanceltype(obj->fCancellation, NULL)) != 0) {
  27. jack_error("pthread_setcanceltype err = %s", strerror(err));
  28. }
  29. // Call Init method
  30. if (!runnable->Init()) {
  31. jack_error("Thread init fails: thread quits");
  32. return 0;
  33. }
  34. JackLog("ThreadHandler: start\n");
  35. // If Init succeed, start the thread loop
  36. while ((obj->fRunning = runnable->Execute())) {
  37. //pthread_testcancel();
  38. }
  39. JackLog("ThreadHandler: exit\n");
  40. return 0;
  41. }
  42. int JackPosixThread::Start()
  43. {
  44. int res;
  45. fRunning = true;
  46. if (fRealTime) {
  47. JackLog("Create RT thread\n");
  48. /* Get the client thread to run as an RT-FIFO
  49. scheduled thread of appropriate priority.
  50. */
  51. pthread_attr_t attributes;
  52. struct sched_param rt_param;
  53. pthread_attr_init(&attributes);
  54. if ((res = pthread_attr_setinheritsched(&attributes, PTHREAD_EXPLICIT_SCHED))) {
  55. jack_error("Cannot request explicit scheduling for RT thread %d %s", res, strerror(errno));
  56. return -1;
  57. }
  58. if ((res = pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_JOINABLE))) {
  59. jack_error("Cannot request joinable thread creation for RT thread %d %s", res, strerror(errno));
  60. return -1;
  61. }
  62. if ((res = pthread_attr_setscope(&attributes, PTHREAD_SCOPE_SYSTEM))) {
  63. jack_error("Cannot set scheduling scope for RT thread %d %s", res, strerror(errno));
  64. return -1;
  65. }
  66. //if ((res = pthread_attr_setschedpolicy(&attributes, SCHED_FIFO))) {
  67. if ((res = pthread_attr_setschedpolicy(&attributes, SCHED_RR))) {
  68. jack_error("Cannot set FIFO scheduling class for RT thread %d %s", res, strerror(errno));
  69. return -1;
  70. }
  71. if ((res = pthread_attr_setscope(&attributes, PTHREAD_SCOPE_SYSTEM))) {
  72. jack_error("Cannot set scheduling scope for RT thread %d %s", res, strerror(errno));
  73. return -1;
  74. }
  75. memset(&rt_param, 0, sizeof(rt_param));
  76. rt_param.sched_priority = fPriority;
  77. if ((res = pthread_attr_setschedparam(&attributes, &rt_param))) {
  78. jack_error("Cannot set scheduling priority for RT thread %d %s", res, strerror(errno));
  79. return -1;
  80. }
  81. if ((res = pthread_create(&fThread, &attributes, ThreadHandler, this))) {
  82. jack_error("Cannot set create thread %d %s", res, strerror(errno));
  83. return -1;
  84. }
  85. return 0;
  86. } else {
  87. JackLog("Create non RT thread\n");
  88. if ((res = pthread_create(&fThread, 0, ThreadHandler, this))) {
  89. jack_error("Cannot set create thread %d %s", res, strerror(errno));
  90. return -1;
  91. }
  92. return 0;
  93. }
  94. }
  95. int JackPosixThread::StartSync()
  96. {
  97. jack_error("Not implemented yet");
  98. return -1;
  99. }
  100. int JackPosixThread::Kill()
  101. {
  102. if (fThread) { // If thread has been started
  103. JackLog("JackPosixThread::Kill\n");
  104. void* status;
  105. pthread_cancel(fThread);
  106. pthread_join(fThread, &status);
  107. fRunning = false;
  108. return 0;
  109. } else {
  110. return -1;
  111. }
  112. }
  113. int JackPosixThread::Stop()
  114. {
  115. if (fThread) { // If thread has been started
  116. JackLog("JackPosixThread::Stop\n");
  117. void* status;
  118. fRunning = false; // Request for the thread to stop
  119. pthread_join(fThread, &status);
  120. return 0;
  121. } else {
  122. return -1;
  123. }
  124. }
  125. int JackPosixThread::AcquireRealTime()
  126. {
  127. struct sched_param rtparam;
  128. int res;
  129. if (!fThread)
  130. return -1;
  131. memset(&rtparam, 0, sizeof(rtparam));
  132. rtparam.sched_priority = fPriority;
  133. //if ((res = pthread_setschedparam(fThread, SCHED_FIFO, &rtparam)) != 0) {
  134. if ((res = pthread_setschedparam(fThread, SCHED_RR, &rtparam)) != 0) {
  135. jack_error("Cannot use real-time scheduling (FIFO/%d) "
  136. "(%d: %s)", rtparam.sched_priority, res,
  137. strerror(res));
  138. return -1;
  139. }
  140. return 0;
  141. }
  142. int JackPosixThread::AcquireRealTime(int priority)
  143. {
  144. fPriority = priority;
  145. return AcquireRealTime();
  146. }
  147. int JackPosixThread::DropRealTime()
  148. {
  149. struct sched_param rtparam;
  150. int res;
  151. if (!fThread)
  152. return -1;
  153. memset(&rtparam, 0, sizeof(rtparam));
  154. rtparam.sched_priority = 0;
  155. if ((res = pthread_setschedparam(fThread, SCHED_OTHER, &rtparam)) != 0) {
  156. jack_error("Cannot switch to normal scheduling priority(%s)\n", strerror(errno));
  157. return -1;
  158. }
  159. return 0;
  160. }
  161. pthread_t JackPosixThread::GetThreadID()
  162. {
  163. return fThread;
  164. }
  165. } // end of namespace