3 |
* LinuxSampler - modular, streaming capable sampler * |
* LinuxSampler - modular, streaming capable sampler * |
4 |
* * |
* * |
5 |
* Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck * |
* Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck * |
6 |
* Copyright (C) 2005 - 2011 Christian Schoenebeck * |
* Copyright (C) 2005 - 2017 Christian Schoenebeck * |
7 |
* * |
* * |
8 |
* This program is free software; you can redistribute it and/or modify * |
* This program is free software; you can redistribute it and/or modify * |
9 |
* it under the terms of the GNU General Public License as published by * |
* it under the terms of the GNU General Public License as published by * |
27 |
# include <config.h> |
# include <config.h> |
28 |
#endif |
#endif |
29 |
|
|
30 |
|
#if DEBUG |
31 |
|
# include <assert.h> |
32 |
|
#endif |
33 |
|
|
34 |
// this is the minimum stack size a thread will be spawned with |
// this is the minimum stack size a thread will be spawned with |
35 |
// if this value is too small, the OS will allocate memory on demand and |
// if this value is too small, the OS will allocate memory on demand and |
36 |
// thus might lead to dropouts in realtime threads |
// thus might lead to dropouts in realtime threads |
39 |
|
|
40 |
namespace LinuxSampler { |
namespace LinuxSampler { |
41 |
|
|
|
#if defined(WIN32) |
|
|
// Callback functions for the WIN32 thread API |
|
|
DWORD WINAPI __win32thread_launcher(LPVOID lpParameter); |
|
|
#else |
|
|
// Callback functions for the POSIX thread API |
|
|
static void* __pthread_launcher(void* thread); |
|
|
static void __pthread_destructor(void* thread); |
|
|
#endif |
|
|
|
|
42 |
Thread::Thread(bool LockMemory, bool RealTime, int PriorityMax, int PriorityDelta) { |
Thread::Thread(bool LockMemory, bool RealTime, int PriorityMax, int PriorityDelta) { |
43 |
this->bLockedMemory = LockMemory; |
this->bLockedMemory = LockMemory; |
44 |
this->isRealTime = RealTime; |
this->isRealTime = RealTime; |
45 |
this->PriorityDelta = PriorityDelta; |
this->PriorityDelta = PriorityDelta; |
46 |
this->PriorityMax = PriorityMax; |
this->PriorityMax = PriorityMax; |
47 |
|
this->state = NOT_RUNNING; |
48 |
#if defined(WIN32) |
#if defined(WIN32) |
49 |
#if defined(WIN32_SIGNALSTARTTHREAD_WORKAROUND) |
# if defined(WIN32_SIGNALSTARTTHREAD_WORKAROUND) |
50 |
win32isRunning = false; |
win32isRunning = false; |
51 |
#endif |
# endif |
52 |
#else |
#else |
53 |
__thread_destructor_key = 0; |
__thread_destructor_key = 0; |
54 |
pthread_attr_init(&__thread_attr); |
pthread_attr_init(&__thread_attr); |
56 |
} |
} |
57 |
|
|
58 |
Thread::~Thread() { |
Thread::~Thread() { |
59 |
StopThread(); |
// The thread must no longer be running at this point, otherwise it is an |
60 |
#if defined(WIN32) |
// error (we should avoid an implied call of StopThread() in the destructor, |
61 |
|
// because trying to do so might cause undefined behavior). |
62 |
|
#if DEBUG |
63 |
|
assert(!RunningCondition.GetUnsafe()); |
64 |
#else |
#else |
65 |
|
if (RunningCondition.GetUnsafe()) { |
66 |
|
std::cerr << "WARNING: Thread destructed while still running!\n" << std::flush; |
67 |
|
StopThread(); |
68 |
|
} |
69 |
|
#endif |
70 |
|
#if !defined(WIN32) |
71 |
pthread_attr_destroy(&__thread_attr); |
pthread_attr_destroy(&__thread_attr); |
72 |
#endif |
#endif |
73 |
} |
} |
74 |
|
|
75 |
/** |
/** |
76 |
* Starts the thread. This method will wait until the thread actually |
* Starts the thread synchronously. This method will block until the thread |
77 |
* started it's execution before it will return. The abstract method |
* actually started it's execution before it will return. The abstract method |
78 |
* Main() is the entry point for the new thread. You have to implement the |
* Main() is the entry point for the new thread. You have to implement the |
79 |
* Main() method in your subclass. |
* Main() method in your subclass. |
80 |
|
* |
81 |
|
* If this thread is already running when this method is called, then this |
82 |
|
* method will detect this and return accordingly without further actions. |
83 |
|
* |
84 |
|
* @returns 0 on success, any other value if thread could not be launched |
85 |
*/ |
*/ |
86 |
int Thread::StartThread() { |
int Thread::StartThread() { |
87 |
|
int res = -1; |
88 |
#if defined (WIN32_SIGNALSTARTTHREAD_WORKAROUND) |
#if defined (WIN32_SIGNALSTARTTHREAD_WORKAROUND) |
89 |
// poll the win32isRunning variable and sleep 1msec inbetween |
// poll the win32isRunning variable and sleep 1msec inbetween |
90 |
if(!win32isRunning) { |
if(!win32isRunning) { |
91 |
SignalStartThread(); |
res = SignalStartThread(); |
92 |
while(1) { |
if (res == 0) { |
93 |
Sleep(1); |
while (true) { |
94 |
if(win32isRunning) break; |
Sleep(1); |
95 |
|
if (win32isRunning) break; |
96 |
|
} |
97 |
} |
} |
98 |
} |
} else res = 0; |
|
return 0; |
|
99 |
#else |
#else |
100 |
RunningCondition.Lock(); |
LockGuard g(RunningCondition); |
101 |
|
// If the thread terminated on its own (i.e. returned from Main()) without |
102 |
|
// any thread calling StopThread() yet, then the OS blocks termination of |
103 |
|
// the thread waiting for a pthread_join() call. So we must detach the |
104 |
|
// thread in this case, because otherwise it will cause a thread leak. |
105 |
|
if (state == PENDING_JOIN) { |
106 |
|
state = DETACHED; |
107 |
|
#if !defined(WIN32) |
108 |
|
pthread_detach(__thread_id); |
109 |
|
#endif |
110 |
|
} |
111 |
if (!RunningCondition.GetUnsafe()) { |
if (!RunningCondition.GetUnsafe()) { |
112 |
SignalStartThread(); |
res = SignalStartThread(); |
113 |
// wait until thread started execution |
// if thread was triggered successfully, wait until thread actually |
114 |
RunningCondition.WaitIf(false); |
// started execution |
115 |
|
if (res == 0) |
116 |
|
RunningCondition.PreLockedWaitIf(false); |
117 |
|
} else { |
118 |
|
res = 0; |
119 |
} |
} |
|
RunningCondition.Unlock(); |
|
|
return 0; |
|
120 |
#endif |
#endif |
121 |
|
return res; |
122 |
} |
} |
123 |
|
|
124 |
/** |
/** |
127 |
* method returns! The abstract method Main() is the entry point for the |
* method returns! The abstract method Main() is the entry point for the |
128 |
* new thread. You have to implement the Main() method in your subclass. |
* new thread. You have to implement the Main() method in your subclass. |
129 |
* |
* |
130 |
|
* @b IMPORTANT: Calling this method assumes that this thread is not yet |
131 |
|
* running! Calling this method if the thread is already running causes |
132 |
|
* undefined behavior! |
133 |
|
* |
134 |
* @see StartThread() |
* @see StartThread() |
135 |
*/ |
*/ |
136 |
int Thread::SignalStartThread() { |
int Thread::SignalStartThread() { |
137 |
|
state = RUNNING; |
138 |
#if defined(WIN32) |
#if defined(WIN32) |
139 |
LPVOID lpParameter; |
LPVOID lpParameter; |
140 |
hThread = CreateThread( |
hThread = CreateThread( |
141 |
NULL, // no security attributes |
NULL, // no security attributes |
142 |
MIN_STACK_SIZE, |
MIN_STACK_SIZE, |
143 |
__win32thread_launcher, |
win32threadLauncher, |
144 |
this, |
this, |
145 |
0, |
0, |
146 |
&lpThreadId); |
&lpThreadId); |
186 |
} |
} |
187 |
|
|
188 |
// Create and run the thread |
// Create and run the thread |
189 |
res = pthread_create(&this->__thread_id, &__thread_attr, __pthread_launcher, this); |
res = pthread_create(&this->__thread_id, &__thread_attr, pthreadLauncher, this); |
190 |
switch (res) { |
switch (res) { |
191 |
case 0: // Success |
case 0: // Success |
192 |
break; |
break; |
211 |
} |
} |
212 |
|
|
213 |
/** |
/** |
214 |
* Stops the thread. This method will wait until the thread actually stopped |
* Stops the thread synchronously. This method will block until the thread |
215 |
* it's execution before it will return. |
* actually stopped its execution before it will return from this method. |
216 |
|
* |
217 |
|
* If the thread is not running when calling this method, this will be detected |
218 |
|
* and the call will be ignored. So it is safe to call this method both if the |
219 |
|
* thread never started, as well as if the thread has already been stopped. And |
220 |
|
* in fact you should explicitly call StopThread() before the Thread object is |
221 |
|
* going to be destructured! |
222 |
|
* |
223 |
|
* @see SignalStopThread() |
224 |
*/ |
*/ |
225 |
int Thread::StopThread() { |
int Thread::StopThread() { |
226 |
#if defined(WIN32_SIGNALSTARTTHREAD_WORKAROUND) |
#if defined(WIN32_SIGNALSTARTTHREAD_WORKAROUND) |
227 |
SignalStopThread(); |
SignalStopThread(); |
228 |
win32isRunning = false; |
win32isRunning = false; |
229 |
return 0; |
return 0; |
230 |
#endif |
#else |
231 |
|
// LockGuard cannot be used here, because this is a bit more tricky here |
232 |
RunningCondition.Lock(); |
RunningCondition.Lock(); |
233 |
|
#if !defined(WIN32) |
234 |
|
// if thread was calling StopThread() on itself |
235 |
|
if (pthread_equal(__thread_id, pthread_self())) { |
236 |
|
RunningCondition.PreLockedSet(false); |
237 |
|
state = DETACHED; |
238 |
|
pthread_detach(__thread_id); |
239 |
|
RunningCondition.Unlock(); |
240 |
|
pthread_exit(NULL); |
241 |
|
} |
242 |
|
#endif |
243 |
|
// if we are here, then any other thread called StopThread() but not the thread itself |
244 |
if (RunningCondition.GetUnsafe()) { |
if (RunningCondition.GetUnsafe()) { |
245 |
SignalStopThread(); |
SignalStopThread(); |
246 |
// wait until thread stopped execution |
// wait until thread stopped execution |
247 |
RunningCondition.WaitIf(true); |
RunningCondition.PreLockedWaitAndUnlockIf(true); |
248 |
#if defined(WIN32) |
#if !defined(WIN32) |
249 |
#else |
pthread_join(__thread_id, NULL); |
250 |
|
#endif |
251 |
|
RunningCondition.Lock(); |
252 |
|
} |
253 |
|
// If the thread terminated on its own (i.e. returned from Main()) without |
254 |
|
// any thread calling StopThread() yet, then the OS blocks termination of |
255 |
|
// the thread waiting for a pthread_join() call. So we must detach the |
256 |
|
// thread in this case, because otherwise it will cause a thread leak. |
257 |
|
if (state == PENDING_JOIN) { |
258 |
|
state = DETACHED; |
259 |
|
#if !defined(WIN32) |
260 |
pthread_detach(__thread_id); |
pthread_detach(__thread_id); |
261 |
#endif |
#endif |
262 |
} |
} |
263 |
RunningCondition.Unlock(); |
RunningCondition.Unlock(); |
264 |
return 0; |
return 0; |
265 |
|
#endif |
266 |
} |
} |
267 |
|
|
268 |
/** |
/** |
269 |
* Stops the thread. This method will signal to stop the thread and return |
* Stops the thread asynchronously. This method will signal to stop the thread |
270 |
* immediately. Note that the thread might still run when this method |
* and return immediately. Note that due to this the thread might still run |
271 |
* returns! |
* when this method returns! |
272 |
|
* |
273 |
|
* @b IMPORTANT: You @ MUST still call StopThread() before destructing the |
274 |
|
* Thread object, even if you called SignalStopThread() before and the thread |
275 |
|
* is no longer running! Otherwise this may lead to a thread leak! |
276 |
* |
* |
277 |
* @see StopThread() |
* @see StopThread() |
278 |
*/ |
*/ |
295 |
} |
} |
296 |
|
|
297 |
/** |
/** |
298 |
* Returns @c true in case the thread is currently running. |
* Returns @c true in case the thread is currently running. This method does not |
299 |
|
* block and returns immediately. |
300 |
|
* |
301 |
|
* Note that no synchronization is performed when calling this method. So the |
302 |
|
* returned result is a very volatile information which must be processed with |
303 |
|
* precautions, that is it may not be used for code that might cause a race |
304 |
|
* condition. |
305 |
*/ |
*/ |
306 |
bool Thread::IsRunning() { |
bool Thread::IsRunning() { |
307 |
#if defined(WIN32_SIGNALSTARTTHREAD_WORKAROUND) |
#if defined(WIN32_SIGNALSTARTTHREAD_WORKAROUND) |
408 |
/** |
/** |
409 |
* Registers thread destructor callback function which will be executed when |
* Registers thread destructor callback function which will be executed when |
410 |
* the thread stops it's execution and sets the 'Running' flag to true. This |
* the thread stops it's execution and sets the 'Running' flag to true. This |
411 |
* method will be called by the __pthread_launcher callback function, DO NOT |
* method will be called by the pthreadLauncher callback function, DO NOT |
412 |
* CALL THIS METHOD YOURSELF! |
* CALL THIS METHOD YOURSELF! |
413 |
*/ |
*/ |
414 |
void Thread::EnableDestructor() { |
void Thread::EnableDestructor() { |
416 |
win32isRunning = true; |
win32isRunning = true; |
417 |
return; |
return; |
418 |
#endif |
#endif |
419 |
RunningCondition.Lock(); |
LockGuard g(RunningCondition); |
420 |
#if defined(WIN32) |
#if !defined(WIN32) |
421 |
#else |
pthread_key_create(&__thread_destructor_key, pthreadDestructor); |
|
pthread_key_create(&__thread_destructor_key, __pthread_destructor); |
|
422 |
pthread_setspecific(__thread_destructor_key, this); |
pthread_setspecific(__thread_destructor_key, this); |
423 |
#endif |
#endif |
424 |
RunningCondition.Set(true); |
RunningCondition.PreLockedSet(true); |
|
RunningCondition.Unlock(); |
|
425 |
} |
} |
426 |
|
|
427 |
/** |
/** |
428 |
* Will be called by the kernel when the thread stops it's execution. |
* May be overridden by deriving classes to add additional custom cleanup |
429 |
|
* code if necessary for the event when thread terminates. Currently this |
430 |
|
* default implementation does nothing. |
431 |
*/ |
*/ |
432 |
int Thread::Destructor() { |
int Thread::onThreadEnd() { |
|
#if defined(WIN32) |
|
|
#else |
|
|
pthread_key_delete(__thread_destructor_key); |
|
|
RunningCondition.Set(false); |
|
|
#endif |
|
433 |
return 0; |
return 0; |
434 |
} |
} |
435 |
|
|
436 |
void Thread::TestCancel() { |
void Thread::TestCancel() { |
437 |
#if CONFIG_PTHREAD_TESTCANCEL |
#if !defined(WIN32) |
438 |
pthread_testcancel(); |
pthread_testcancel(); |
439 |
#endif |
#endif |
440 |
} |
} |
444 |
// make sure stack is 16-byte aligned for SSE instructions |
// make sure stack is 16-byte aligned for SSE instructions |
445 |
__attribute__((force_align_arg_pointer)) |
__attribute__((force_align_arg_pointer)) |
446 |
#endif |
#endif |
447 |
DWORD WINAPI __win32thread_launcher(LPVOID lpParameter) { |
DWORD WINAPI Thread::win32threadLauncher(LPVOID lpParameter) { |
448 |
Thread* t; |
Thread* t; |
449 |
t = (Thread*) lpParameter; |
t = (Thread*) lpParameter; |
450 |
t->SetSchedulingPriority(); |
t->SetSchedulingPriority(); |
455 |
} |
} |
456 |
#else |
#else |
457 |
/// Callback function for the POSIX thread API |
/// Callback function for the POSIX thread API |
458 |
static void* __pthread_launcher(void* thread) { |
void* Thread::pthreadLauncher(void* thread) { |
459 |
#if !CONFIG_PTHREAD_TESTCANCEL |
#if !CONFIG_PTHREAD_TESTCANCEL |
460 |
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); // let the thread be killable under any circumstances |
// let the thread be killable under any circumstances |
461 |
|
if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) { |
462 |
|
std::cerr << "Thread: WARNING, PTHREAD_CANCEL_ASYNCHRONOUS not supported!\n" << std::flush; |
463 |
|
} |
464 |
#endif |
#endif |
465 |
|
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); |
466 |
Thread* t; |
Thread* t; |
467 |
t = (Thread*) thread; |
t = (Thread*) thread; |
468 |
t->SetSchedulingPriority(); |
t->SetSchedulingPriority(); |
473 |
} |
} |
474 |
#endif |
#endif |
475 |
|
|
476 |
#if defined(WIN32) |
#if !defined(WIN32) |
|
#else |
|
477 |
/// Callback function for the POSIX thread API |
/// Callback function for the POSIX thread API |
478 |
static void __pthread_destructor(void* thread) { |
void Thread::pthreadDestructor(void* thread) { |
479 |
Thread* t; |
Thread* t; |
480 |
t = (Thread*) thread; |
t = (Thread*) thread; |
481 |
t->Destructor(); |
LockGuard g(t->RunningCondition); |
482 |
|
t->onThreadEnd(); |
483 |
|
pthread_key_delete(t->__thread_destructor_key); |
484 |
|
// inform that thread termination blocks waiting for pthread_join() |
485 |
|
// (not detaching the thread here already, because otherwise this might lead |
486 |
|
// to a data race of the vpointer with the Thread object destructor) |
487 |
|
t->state = PENDING_JOIN; |
488 |
|
t->RunningCondition.PreLockedSet(false); |
489 |
} |
} |
490 |
#endif |
#endif |
491 |
|
|