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.

317 lines
7.7KB

  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. int JackWinThread::StartImp(jack_native_thread_t* thread, int priority, int realtime, void*(*start_routine)(void*), void* arg)
  101. {
  102. return JackWinThread::StartImp(thread, priority, realtime, (ThreadCallback) start_routine, arg);
  103. }
  104. // voir http://www.microsoft.com/belux/msdn/nl/community/columns/ldoc/multithread1.mspx
  105. int JackWinThread::Kill()
  106. {
  107. if (fThread != (HANDLE)NULL) { // If thread has been started
  108. TerminateThread(fThread, 0);
  109. WaitForSingleObject(fThread, INFINITE);
  110. CloseHandle(fThread);
  111. jack_log("JackWinThread::Kill");
  112. fThread = (HANDLE)NULL;
  113. fStatus = kIdle;
  114. return 0;
  115. } else {
  116. return -1;
  117. }
  118. }
  119. int JackWinThread::Stop()
  120. {
  121. if (fThread != (HANDLE)NULL) { // If thread has been started
  122. jack_log("JackWinThread::Stop");
  123. fStatus = kIdle; // Request for the thread to stop
  124. WaitForSingleObject(fEvent, INFINITE);
  125. CloseHandle(fThread);
  126. fThread = (HANDLE)NULL;
  127. return 0;
  128. } else {
  129. return -1;
  130. }
  131. }
  132. int JackWinThread::KillImp(jack_native_thread_t thread)
  133. {
  134. if (thread != (HANDLE)NULL) { // If thread has been started
  135. TerminateThread(thread, 0);
  136. WaitForSingleObject(thread, INFINITE);
  137. CloseHandle(thread);
  138. return 0;
  139. } else {
  140. return -1;
  141. }
  142. }
  143. int JackWinThread::StopImp(jack_native_thread_t thread)
  144. {
  145. if (thread) { // If thread has been started
  146. WaitForSingleObject(thread, INFINITE);
  147. CloseHandle(thread);
  148. return 0;
  149. } else {
  150. return -1;
  151. }
  152. }
  153. int JackWinThread::AcquireRealTimeImp(jack_native_thread_t thread, int priority, UInt64 period, UInt64 computation, UInt64 constraintt)
  154. {
  155. jack_log("JackWinThread::AcquireRealTimeImp priority = %d", priority);
  156. if (priority >= (BASE_REALTIME_PRIORITY - 1) && MMCSSAcquireRealTime(thread, priority) == 0) {
  157. jack_log("MMCSS API used to acquire RT for thread");
  158. return 0;
  159. } else {
  160. jack_log("MMCSS API not used...");
  161. if (SetThreadPriority(thread, THREAD_PRIORITY_TIME_CRITICAL)) {
  162. return 0;
  163. } else {
  164. jack_error("Cannot set thread priority = %d", GetLastError());
  165. return -1;
  166. }
  167. }
  168. }
  169. int JackWinThread::AcquireRealTime()
  170. {
  171. return (fThread != (HANDLE)NULL) ? JackWinThread::AcquireRealTimeImp(fThread, fPriority, NULL, NULL, NULL) : -1;
  172. }
  173. int JackWinThread::AcquireSelfRealTime()
  174. {
  175. return JackWinThread::AcquireRealTimeImp(GetCurrentThread(), fPriority, NULL, NULL, NULL);
  176. }
  177. int JackWinThread::AcquireRealTime(int priority)
  178. {
  179. fPriority = priority;
  180. return AcquireRealTime();
  181. }
  182. int JackWinThread::AcquireSelfRealTime(int priority)
  183. {
  184. fPriority = priority;
  185. return AcquireSelfRealTime();
  186. }
  187. int JackWinThread::DropRealTime()
  188. {
  189. return (fThread != (HANDLE)NULL) ? DropRealTimeImp(fThread) : -1;
  190. }
  191. int JackWinThread::DropSelfRealTime()
  192. {
  193. return DropRealTimeImp(GetCurrentThread());
  194. }
  195. int JackWinThread::DropRealTimeImp(jack_native_thread_t thread)
  196. {
  197. if (MMCSSDropRealTime(thread) == 0) {
  198. jack_log("MMCSS API used to drop RT for thread");
  199. return 0;
  200. } else if (SetThreadPriority(thread, THREAD_PRIORITY_NORMAL)) {
  201. return 0;
  202. } else {
  203. jack_error("Cannot set thread priority = %d", GetLastError());
  204. return -1;
  205. }
  206. }
  207. jack_native_thread_t JackWinThread::GetThreadID()
  208. {
  209. return fThread;
  210. }
  211. bool JackWinThread::IsThread()
  212. {
  213. return GetCurrentThread() == fThread;
  214. }
  215. void JackWinThread::Terminate()
  216. {
  217. jack_log("JackWinThread::Terminate");
  218. ExitThread(0);
  219. }
  220. SERVER_EXPORT void ThreadExit()
  221. {
  222. jack_log("ThreadExit");
  223. ExitThread(0);
  224. }
  225. } // end of namespace
  226. bool jack_get_thread_realtime_priority_range(int * min_ptr, int * max_ptr)
  227. {
  228. return false;
  229. }
  230. bool jack_tls_allocate_key(jack_tls_key *key_ptr)
  231. {
  232. DWORD key;
  233. key = TlsAlloc();
  234. if (key == TLS_OUT_OF_INDEXES)
  235. {
  236. jack_error("TlsAlloc() failed. Error is %d", (unsigned int)GetLastError());
  237. return false;
  238. }
  239. *key_ptr = key;
  240. return true;
  241. }
  242. bool jack_tls_free_key(jack_tls_key key)
  243. {
  244. if (!TlsFree(key))
  245. {
  246. jack_error("TlsFree() failed. Error is %d", (unsigned int)GetLastError());
  247. return false;
  248. }
  249. return true;
  250. }
  251. bool jack_tls_set(jack_tls_key key, void *data_ptr)
  252. {
  253. if (!TlsSetValue(key, data_ptr))
  254. {
  255. jack_error("TlsSetValue() failed. Error is %d", (unsigned int)GetLastError());
  256. return false;
  257. }
  258. return true;
  259. }
  260. void *jack_tls_get(jack_tls_key key)
  261. {
  262. return TlsGetValue(key);
  263. }