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.

387 lines
9.5KB

  1. /*
  2. Copyright (C) 2001 Paul Davis
  3. Copyright (C) 2004-2008 Grame
  4. Copyright (C) 2013 Samsung Electronics
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU Lesser General Public License as published by
  7. the Free Software Foundation; either version 2.1 of the License, or
  8. (at your option) any later version.
  9. This program 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
  12. GNU Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  16. */
  17. #include "JackAndroidThread.h"
  18. #include "JackError.h"
  19. #include "JackTime.h"
  20. #include "JackGlobals.h"
  21. #include <string.h> // for memset
  22. #include <unistd.h> // for _POSIX_PRIORITY_SCHEDULING check
  23. #include <signal.h>
  24. #ifdef JACK_ANDROID_REALTIME_SCHED
  25. #include "SchedulingPolicyService.h"
  26. #endif
  27. //#define JACK_SCHED_POLICY SCHED_RR
  28. #define JACK_SCHED_POLICY SCHED_FIFO
  29. namespace Jack
  30. {
  31. void JackAndroidThread::thread_exit_handler(int sig)
  32. {
  33. printf("this signal is %d \n", sig);
  34. pthread_exit(0);
  35. }
  36. void* JackAndroidThread::ThreadHandler(void* arg)
  37. {
  38. JackAndroidThread* obj = (JackAndroidThread*)arg;
  39. JackRunnableInterface* runnable = obj->fRunnable;
  40. int err;
  41. // Signal creation thread when started with StartSync
  42. jack_log("JackAndroidThread::ThreadHandler : start");
  43. obj->fStatus = kIniting;
  44. // Call Init method
  45. if (!runnable->Init()) {
  46. jack_error("Thread init fails: thread quits");
  47. return 0;
  48. }
  49. obj->fStatus = kRunning;
  50. // If Init succeed, start the thread loop
  51. bool res = true;
  52. while (obj->fStatus == kRunning && res) {
  53. res = runnable->Execute();
  54. }
  55. jack_log("JackAndroidThread::ThreadHandler : exit");
  56. pthread_exit(0);
  57. return 0; // never reached
  58. }
  59. int JackAndroidThread::Start()
  60. {
  61. fStatus = kStarting;
  62. // Check if the thread was correctly started
  63. if (StartImp(&fThread, fPriority, fRealTime, ThreadHandler, this) < 0) {
  64. fStatus = kIdle;
  65. return -1;
  66. } else {
  67. return 0;
  68. }
  69. }
  70. int JackAndroidThread::StartSync()
  71. {
  72. fStatus = kStarting;
  73. if (StartImp(&fThread, fPriority, fRealTime, ThreadHandler, this) < 0) {
  74. fStatus = kIdle;
  75. return -1;
  76. } else {
  77. int count = 0;
  78. while (fStatus == kStarting && ++count < 1000) {
  79. JackSleep(1000);
  80. }
  81. return (count == 1000) ? -1 : 0;
  82. }
  83. }
  84. int JackAndroidThread::StartImp(jack_native_thread_t* thread, int priority, int realtime, void*(*start_routine)(void*), void* arg)
  85. {
  86. pthread_attr_t attributes;
  87. struct sched_param rt_param;
  88. pthread_attr_init(&attributes);
  89. int res;
  90. struct sigaction actions;
  91. memset(&actions, 0, sizeof(actions));
  92. sigemptyset(&actions.sa_mask);
  93. actions.sa_flags = 0;
  94. actions.sa_handler = thread_exit_handler;
  95. sigaction(SIGUSR1,&actions,NULL);
  96. if ((res = pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_JOINABLE))) {
  97. jack_error("Cannot request joinable thread creation for thread res = %d", res);
  98. return -1;
  99. }
  100. if ((res = pthread_attr_setscope(&attributes, PTHREAD_SCOPE_SYSTEM))) {
  101. jack_error("Cannot set scheduling scope for thread res = %d", res);
  102. return -1;
  103. }
  104. if (realtime) {
  105. jack_log("JackAndroidThread::StartImp : create RT thread");
  106. if ((res = pthread_attr_setschedpolicy(&attributes, JACK_SCHED_POLICY))) {
  107. jack_error("Cannot set RR scheduling class for RT thread res = %d", res);
  108. return -1;
  109. }
  110. memset(&rt_param, 0, sizeof(rt_param));
  111. rt_param.sched_priority = priority;
  112. if ((res = pthread_attr_setschedparam(&attributes, &rt_param))) {
  113. jack_error("Cannot set scheduling priority for RT thread res = %d", res);
  114. return -1;
  115. }
  116. } else {
  117. jack_log("JackAndroidThread::StartImp : create non RT thread");
  118. }
  119. if ((res = pthread_attr_setstacksize(&attributes, THREAD_STACK))) {
  120. jack_error("Cannot set thread stack size res = %d", res);
  121. return -1;
  122. }
  123. if ((res = JackGlobals::fJackThreadCreator(thread, &attributes, start_routine, arg))) {
  124. jack_error("Cannot create thread res = %d", res);
  125. return -1;
  126. }
  127. pthread_attr_destroy(&attributes);
  128. return 0;
  129. }
  130. int JackAndroidThread::Kill()
  131. {
  132. if (fThread != (jack_native_thread_t)NULL) { // If thread has been started
  133. jack_log("JackAndroidThread::Kill");
  134. void* status;
  135. pthread_kill(fThread, SIGUSR1);
  136. pthread_join(fThread, &status);
  137. fStatus = kIdle;
  138. fThread = (jack_native_thread_t)NULL;
  139. return 0;
  140. } else {
  141. return -1;
  142. }
  143. }
  144. int JackAndroidThread::Stop()
  145. {
  146. if (fThread != (jack_native_thread_t)NULL) { // If thread has been started
  147. jack_log("JackAndroidThread::Stop");
  148. void* status;
  149. fStatus = kIdle; // Request for the thread to stop
  150. pthread_join(fThread, &status);
  151. fThread = (jack_native_thread_t)NULL;
  152. return 0;
  153. } else {
  154. return -1;
  155. }
  156. }
  157. int JackAndroidThread::KillImp(jack_native_thread_t thread)
  158. {
  159. if (thread != (jack_native_thread_t)NULL) { // If thread has been started
  160. jack_log("JackAndroidThread::Kill");
  161. void* status;
  162. pthread_kill(thread, SIGUSR1);
  163. pthread_join(thread, &status);
  164. return 0;
  165. } else {
  166. return -1;
  167. }
  168. }
  169. int JackAndroidThread::StopImp(jack_native_thread_t thread)
  170. {
  171. if (thread != (jack_native_thread_t)NULL) { // If thread has been started
  172. jack_log("JackAndroidThread::Stop");
  173. void* status;
  174. pthread_join(thread, &status);
  175. return 0;
  176. } else {
  177. return -1;
  178. }
  179. }
  180. int JackAndroidThread::AcquireRealTime()
  181. {
  182. return (fThread != (jack_native_thread_t)NULL) ? AcquireRealTimeImp(fThread, fPriority) : -1;
  183. }
  184. int JackAndroidThread::AcquireSelfRealTime()
  185. {
  186. return AcquireRealTimeImp(pthread_self(), fPriority);
  187. }
  188. int JackAndroidThread::AcquireRealTime(int priority)
  189. {
  190. fPriority = priority;
  191. return AcquireRealTime();
  192. }
  193. int JackAndroidThread::AcquireSelfRealTime(int priority)
  194. {
  195. fPriority = priority;
  196. return AcquireSelfRealTime();
  197. }
  198. int JackAndroidThread::AcquireRealTimeImp(jack_native_thread_t thread, int priority)
  199. {
  200. struct sched_param rtparam;
  201. int res;
  202. memset(&rtparam, 0, sizeof(rtparam));
  203. rtparam.sched_priority = priority;
  204. jack_log("JackAndroidThread::AcquireRealTimeImp priority = %d", priority);
  205. #ifndef JACK_ANDROID_REALTIME_SCHED
  206. if ((res = pthread_setschedparam(thread, JACK_SCHED_POLICY, &rtparam)) != 0) {
  207. jack_error("Cannot use real-time scheduling (RR/%d)"
  208. "(%d: %s)", rtparam.sched_priority, res,
  209. strerror(res));
  210. return -1;
  211. }
  212. #else
  213. if ((res = android::requestPriority(getpid(), gettid(), priority)) != 0) {
  214. jack_log("Failed to get SCHED_FIFO priority pid %d tid %d; error %d",
  215. getpid(), gettid(), res);
  216. return -1;
  217. }
  218. #endif
  219. return 0;
  220. }
  221. int JackAndroidThread::DropRealTime()
  222. {
  223. return (fThread != (jack_native_thread_t)NULL) ? DropRealTimeImp(fThread) : -1;
  224. }
  225. int JackAndroidThread::DropSelfRealTime()
  226. {
  227. return DropRealTimeImp(pthread_self());
  228. }
  229. int JackAndroidThread::DropRealTimeImp(jack_native_thread_t thread)
  230. {
  231. struct sched_param rtparam;
  232. int res;
  233. memset(&rtparam, 0, sizeof(rtparam));
  234. rtparam.sched_priority = 0;
  235. if ((res = pthread_setschedparam(thread, SCHED_OTHER, &rtparam)) != 0) {
  236. jack_error("Cannot switch to normal scheduling priority(%s)", strerror(errno));
  237. return -1;
  238. }
  239. return 0;
  240. }
  241. jack_native_thread_t JackAndroidThread::GetThreadID()
  242. {
  243. return fThread;
  244. }
  245. bool JackAndroidThread::IsThread()
  246. {
  247. return pthread_self() == fThread;
  248. }
  249. void JackAndroidThread::Terminate()
  250. {
  251. jack_log("JackAndroidThread::Terminate");
  252. pthread_exit(0);
  253. }
  254. SERVER_EXPORT void ThreadExit()
  255. {
  256. jack_log("ThreadExit");
  257. pthread_exit(0);
  258. }
  259. } // end of namespace
  260. bool jack_get_thread_realtime_priority_range(int * min_ptr, int * max_ptr)
  261. {
  262. #if defined(_POSIX_PRIORITY_SCHEDULING) && !defined(__APPLE__)
  263. int min, max;
  264. min = sched_get_priority_min(JACK_SCHED_POLICY);
  265. if (min == -1)
  266. {
  267. jack_error("sched_get_priority_min() failed.");
  268. return false;
  269. }
  270. max = sched_get_priority_max(JACK_SCHED_POLICY);
  271. if (max == -1)
  272. {
  273. jack_error("sched_get_priority_max() failed.");
  274. return false;
  275. }
  276. *min_ptr = min;
  277. *max_ptr = max;
  278. return true;
  279. #else
  280. return false;
  281. #endif
  282. }
  283. bool jack_tls_allocate_key(jack_tls_key *key_ptr)
  284. {
  285. int ret;
  286. ret = pthread_key_create(key_ptr, NULL);
  287. if (ret != 0)
  288. {
  289. jack_error("pthread_key_create() failed with error %d", ret);
  290. return false;
  291. }
  292. return true;
  293. }
  294. bool jack_tls_free_key(jack_tls_key key)
  295. {
  296. int ret;
  297. ret = pthread_key_delete(key);
  298. if (ret != 0)
  299. {
  300. jack_error("pthread_key_delete() failed with error %d", ret);
  301. return false;
  302. }
  303. return true;
  304. }
  305. bool jack_tls_set(jack_tls_key key, void *data_ptr)
  306. {
  307. int ret;
  308. ret = pthread_setspecific(key, (const void *)data_ptr);
  309. if (ret != 0)
  310. {
  311. jack_error("pthread_setspecific() failed with error %d", ret);
  312. return false;
  313. }
  314. return true;
  315. }
  316. void *jack_tls_get(jack_tls_key key)
  317. {
  318. return pthread_getspecific(key);
  319. }