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.

312 lines
7.3KB

  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 "JackWinThread.h"
  16. #include "JackError.h"
  17. #include "JackTime.h"
  18. #include <assert.h>
  19. #include <stdio.h>
  20. namespace Jack
  21. {
  22. DWORD WINAPI JackWinThread::ThreadHandler(void* arg)
  23. {
  24. JackWinThread* obj = (JackWinThread*)arg;
  25. JackRunnableInterface* runnable = obj->fRunnable;
  26. // Signal creation thread when started with StartSync
  27. jack_log("JackWinThread::ThreadHandler : start");
  28. obj->fStatus = kIniting;
  29. // Call Init method
  30. if (!runnable->Init()) {
  31. jack_error("Thread init fails: thread quits");
  32. return 0;
  33. }
  34. obj->fStatus = kRunning;
  35. // If Init succeed, start the thread loop
  36. bool res = true;
  37. while (obj->fStatus == kRunning && res) {
  38. res = runnable->Execute();
  39. }
  40. SetEvent(obj->fEvent);
  41. jack_log("JackWinThread::ThreadHandler : exit");
  42. return 0;
  43. }
  44. JackWinThread::JackWinThread(JackRunnableInterface* runnable)
  45. : JackMMCSS(), JackThreadInterface(runnable, 0, false, 0)
  46. {
  47. fEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  48. fThread = (HANDLE)NULL;
  49. assert(fEvent);
  50. }
  51. JackWinThread::~JackWinThread()
  52. {
  53. CloseHandle(fEvent);
  54. CloseHandle(fThread);
  55. }
  56. int JackWinThread::Start()
  57. {
  58. fStatus = kStarting;
  59. // Check if the thread was correctly started
  60. if (StartImp(&fThread, fPriority, fRealTime, ThreadHandler, this) < 0) {
  61. fStatus = kIdle;
  62. return -1;
  63. } else {
  64. return 0;
  65. }
  66. }
  67. int JackWinThread::StartSync()
  68. {
  69. fStatus = kStarting;
  70. if (StartImp(&fThread, fPriority, fRealTime, ThreadHandler, this) < 0) {
  71. fStatus = kIdle;
  72. return -1;
  73. } else {
  74. int count = 0;
  75. while (fStatus == kStarting && ++count < 1000) {
  76. JackSleep(1000);
  77. }
  78. return (count == 1000) ? -1 : 0;
  79. }
  80. }
  81. int JackWinThread::StartImp(jack_native_thread_t* thread, int priority, int realtime, ThreadCallback start_routine, void* arg)
  82. {
  83. DWORD id;
  84. *thread = CreateThread(NULL, 0, start_routine, arg, 0, &id);
  85. if (*thread == NULL) {
  86. jack_error("Cannot create thread error = %d", GetLastError());
  87. return -1;
  88. }
  89. if (realtime) {
  90. jack_log("JackWinThread::StartImp : create RT thread");
  91. if (!SetThreadPriority(*thread, THREAD_PRIORITY_TIME_CRITICAL)) {
  92. jack_error("Cannot set priority class = %d", GetLastError());
  93. return -1;
  94. }
  95. } else {
  96. jack_log("JackWinThread::StartImp : create non RT thread");
  97. }
  98. return 0;
  99. }
  100. // voir http://www.microsoft.com/belux/msdn/nl/community/columns/ldoc/multithread1.mspx
  101. int JackWinThread::Kill()
  102. {
  103. if (fThread != (HANDLE)NULL) { // If thread has been started
  104. TerminateThread(fThread, 0);
  105. WaitForSingleObject(fThread, INFINITE);
  106. CloseHandle(fThread);
  107. jack_log("JackWinThread::Kill");
  108. fThread = (HANDLE)NULL;
  109. fStatus = kIdle;
  110. return 0;
  111. } else {
  112. return -1;
  113. }
  114. }
  115. int JackWinThread::Stop()
  116. {
  117. if (fThread != (HANDLE)NULL) { // If thread has been started
  118. jack_log("JackWinThread::Stop");
  119. fStatus = kIdle; // Request for the thread to stop
  120. WaitForSingleObject(fEvent, INFINITE);
  121. CloseHandle(fThread);
  122. fThread = (HANDLE)NULL;
  123. return 0;
  124. } else {
  125. return -1;
  126. }
  127. }
  128. int JackWinThread::KillImp(jack_native_thread_t thread)
  129. {
  130. if (thread != (HANDLE)NULL) { // If thread has been started
  131. TerminateThread(thread, 0);
  132. WaitForSingleObject(thread, INFINITE);
  133. CloseHandle(thread);
  134. return 0;
  135. } else {
  136. return -1;
  137. }
  138. }
  139. int JackWinThread::StopImp(jack_native_thread_t thread)
  140. {
  141. if (thread) { // If thread has been started
  142. WaitForSingleObject(thread, INFINITE);
  143. CloseHandle(thread);
  144. return 0;
  145. } else {
  146. return -1;
  147. }
  148. }
  149. int JackWinThread::AcquireRealTime()
  150. {
  151. return (fThread != (HANDLE)NULL) ? AcquireRealTimeImp(fThread, fPriority) : -1;
  152. }
  153. int JackWinThread::AcquireSelfRealTime()
  154. {
  155. return AcquireRealTimeImp(GetCurrentThread(), fPriority);
  156. }
  157. int JackWinThread::AcquireRealTime(int priority)
  158. {
  159. fPriority = priority;
  160. return AcquireRealTime();
  161. }
  162. int JackWinThread::AcquireSelfRealTime(int priority)
  163. {
  164. fPriority = priority;
  165. return AcquireSelfRealTime();
  166. }
  167. int JackWinThread::AcquireRealTimeImp(jack_native_thread_t thread, int priority)
  168. {
  169. jack_log("JackWinThread::AcquireRealTimeImp priority = %d", priority);
  170. if (priority >= 90 && MMCSSAcquireRealTime(thread) == 0) {
  171. jack_log("MMCSS API used to acquire RT for thread");
  172. return 0;
  173. } else {
  174. jack_log("MMCSS API not used...");
  175. if (SetThreadPriority(thread, THREAD_PRIORITY_TIME_CRITICAL)) {
  176. return 0;
  177. } else {
  178. jack_error("Cannot set thread priority = %d", GetLastError());
  179. return -1;
  180. }
  181. }
  182. }
  183. int JackWinThread::DropRealTime()
  184. {
  185. return (fThread != (HANDLE)NULL) ? DropRealTimeImp(fThread) : -1;
  186. }
  187. int JackWinThread::DropSelfRealTime()
  188. {
  189. return DropRealTimeImp(GetCurrentThread());
  190. }
  191. int JackWinThread::DropRealTimeImp(jack_native_thread_t thread)
  192. {
  193. if (MMCSSDropRealTime(thread) == 0) {
  194. jack_log("MMCSS API used to drop RT for thread");
  195. return 0;
  196. } else if (SetThreadPriority(thread, THREAD_PRIORITY_NORMAL)) {
  197. return 0;
  198. } else {
  199. jack_error("Cannot set thread priority = %d", GetLastError());
  200. return -1;
  201. }
  202. }
  203. jack_native_thread_t JackWinThread::GetThreadID()
  204. {
  205. return fThread;
  206. }
  207. bool JackWinThread::IsThread()
  208. {
  209. return GetCurrentThread() == fThread;
  210. }
  211. void JackWinThread::Terminate()
  212. {
  213. jack_log("JackWinThread::Terminate");
  214. ExitThread(0);
  215. }
  216. SERVER_EXPORT void ThreadExit()
  217. {
  218. jack_log("ThreadExit");
  219. ExitThread(0);
  220. }
  221. } // end of namespace
  222. bool jack_get_thread_realtime_priority_range(int * min_ptr, int * max_ptr)
  223. {
  224. return false;
  225. }
  226. bool jack_tls_allocate_key(jack_tls_key *key_ptr)
  227. {
  228. DWORD key;
  229. key = TlsAlloc();
  230. if (key == TLS_OUT_OF_INDEXES)
  231. {
  232. jack_error("TlsAlloc() failed. Error is %d", (unsigned int)GetLastError());
  233. return false;
  234. }
  235. *key_ptr = key;
  236. return true;
  237. }
  238. bool jack_tls_free_key(jack_tls_key key)
  239. {
  240. if (!TlsFree(key))
  241. {
  242. jack_error("TlsFree() failed. Error is %d", (unsigned int)GetLastError());
  243. return false;
  244. }
  245. return true;
  246. }
  247. bool jack_tls_set(jack_tls_key key, void *data_ptr)
  248. {
  249. if (!TlsSetValue(key, data_ptr))
  250. {
  251. jack_error("TlsSetValue() failed. Error is %d", (unsigned int)GetLastError());
  252. return false;
  253. }
  254. return true;
  255. }
  256. void *jack_tls_get(jack_tls_key key)
  257. {
  258. return TlsGetValue(key);
  259. }