1 /***************************************************************************
2  *                                                                         *
3  *   LinuxSampler - modular, streaming capable sampler                     *
4  *                                                                         *
5  *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *
6  *   Copyright (C) 2005 - 2020 Christian Schoenebeck                       *
7  *                                                                         *
8  *   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  *
10  *   the Free Software Foundation; either version 2 of the License, or     *
11  *   (at your option) any later version.                                   *
12  *                                                                         *
13  *   This program is distributed in the hope that it will be useful,       *
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
16  *   GNU General Public License for more details.                          *
17  *                                                                         *
18  *   You should have received a copy of the GNU General Public License     *
19  *   along with this program; if not, write to the Free Software           *
20  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
21  *   MA  02111-1307  USA                                                   *
22  ***************************************************************************/
23 
24 #include "Thread.h"
25 
26 #if HAVE_CONFIG_H
27 # include <config.h>
28 #endif
29 #include "global_private.h"
30 
31 #include <list>
32 #if DEBUG
33 # include <assert.h>
34 #endif
35 
36 #if !CONFIG_PTHREAD_TESTCANCEL
37 # warning No pthread_testcancel() available: this may lead to mutex dead locks when threads are stopped!
38 #endif
39 
40 // this is the minimum stack size a thread will be spawned with
41 // if this value is too small, the OS will allocate memory on demand and
42 // thus might lead to dropouts in realtime threads
43 // TODO: should be up for testing to get a reasonable good value
44 #define MIN_STACK_SIZE		524288
45 
46 #if !defined(WIN32)
47 static thread_local std::list<int> cancelStates;
48 #endif
49 
50 namespace LinuxSampler {
51 
Thread(bool LockMemory,bool RealTime,int PriorityMax,int PriorityDelta)52 Thread::Thread(bool LockMemory, bool RealTime, int PriorityMax, int PriorityDelta) {
53     this->bLockedMemory     = LockMemory;
54     this->isRealTime        = RealTime;
55     this->PriorityDelta     = PriorityDelta;
56     this->PriorityMax       = PriorityMax;
57     this->state = NOT_RUNNING;
58 #if defined(WIN32)
59 # if defined(WIN32_SIGNALSTARTTHREAD_WORKAROUND)
60     win32isRunning = false;
61 # endif
62 #else
63     __thread_destructor_key = 0;
64     pthread_attr_init(&__thread_attr);
65 #endif
66 }
67 
~Thread()68 Thread::~Thread() {
69     // The thread must no longer be running at this point, otherwise it is an
70     // error (we should avoid an implied call of StopThread() in the destructor,
71     // because trying to do so might cause undefined behavior).
72 #if DEBUG
73     assert(!RunningCondition.GetUnsafe());
74 #else
75     if (RunningCondition.GetUnsafe()) {
76         std::cerr << "WARNING: Thread destructed while still running!\n" << std::flush;
77         StopThread();
78     }
79 #endif
80 #if !defined(WIN32)
81     pthread_attr_destroy(&__thread_attr);
82 #endif
83 }
84 
85 /**
86  *  Starts the thread synchronously. This method will block until the thread
87  *  actually started it's execution before it will return. The abstract method
88  *  Main() is the entry point for the new thread. You have to implement the
89  *  Main() method in your subclass.
90  *
91  *  If this thread is already running when this method is called, then this
92  *  method will detect this and return accordingly without further actions.
93  *
94  *  @returns   0 on success, any other value if thread could not be launched
95  */
StartThread()96 int Thread::StartThread() {
97     int res = -1;
98 #if defined (WIN32_SIGNALSTARTTHREAD_WORKAROUND)
99     // poll the win32isRunning variable and sleep 1msec inbetween
100     if(!win32isRunning) {
101         res = SignalStartThread();
102         if (res == 0) {
103             while (true) {
104                 Sleep(1);
105                 if (win32isRunning) break;
106             }
107         }
108     } else res = 0;
109 #else
110     LockGuard g(RunningCondition);
111     // If the thread terminated on its own (i.e. returned from Main()) without
112     // any thread calling StopThread() yet, then the OS blocks termination of
113     // the thread waiting for a pthread_join() call. So we must detach the
114     // thread in this case, because otherwise it will cause a thread leak.
115     if (state == PENDING_JOIN) {
116         state = DETACHED;
117         #if !defined(WIN32)
118         pthread_detach(__thread_id);
119         #endif
120     }
121     if (!RunningCondition.GetUnsafe()) {
122         res = SignalStartThread();
123         // if thread was triggered successfully, wait until thread actually
124         // started execution
125         if (res == 0)
126             RunningCondition.PreLockedWaitIf(false);
127     } else {
128         res = 0;
129     }
130 #endif
131     return res;
132 }
133 
134 /**
135  *  Starts the thread. This method will signal to start the thread and
136  *  return immediately. Note that the thread might not yet run when this
137  *  method returns! The abstract method Main() is the entry point for the
138  *  new thread. You have to implement the Main() method in your subclass.
139  *
140  *  @b IMPORTANT: Calling this method assumes that this thread is not yet
141  *  running! Calling this method if the thread is already running causes
142  *  undefined behavior!
143  *
144  *  @see StartThread()
145  */
SignalStartThread()146 int Thread::SignalStartThread() {
147     state = RUNNING;
148 #if defined(WIN32)
149     LPVOID lpParameter;
150     hThread = CreateThread(
151                NULL, // no security attributes
152                MIN_STACK_SIZE,
153                win32threadLauncher,
154                this,
155                0,
156                &lpThreadId);
157     if(hThread == NULL) {
158         std::cerr << "Thread creation failed: Error" << GetLastError() << std::endl << std::flush;
159         #if defined(WIN32_SIGNALSTARTTHREAD_WORKAROUND)
160         win32isRunning = false;
161         #else
162         RunningCondition.Set(false);
163         #endif
164         return -1;
165     }
166     return 0;
167 #else
168     // prepare the thread properties
169     int res = pthread_attr_setinheritsched(&__thread_attr, PTHREAD_EXPLICIT_SCHED);
170     if (res) {
171         std::cerr << "Thread creation failed: Could not inherit thread properties."
172                   << std::endl << std::flush;
173         RunningCondition.Set(false);
174         return res;
175     }
176     res = pthread_attr_setdetachstate(&__thread_attr, PTHREAD_CREATE_JOINABLE);
177     if (res) {
178         std::cerr << "Thread creation failed: Could not request a joinable thread."
179                   << std::endl << std::flush;
180         RunningCondition.Set(false);
181         return res;
182     }
183     res = pthread_attr_setscope(&__thread_attr, PTHREAD_SCOPE_SYSTEM);
184     if (res) {
185         std::cerr << "Thread creation failed: Could not request system scope for thread scheduling."
186                   << std::endl << std::flush;
187         RunningCondition.Set(false);
188         return res;
189     }
190     res = pthread_attr_setstacksize(&__thread_attr, MIN_STACK_SIZE);
191     if (res) {
192         std::cerr << "Thread creation failed: Could not set minimum stack size."
193                   << std::endl << std::flush;
194         RunningCondition.Set(false);
195         return res;
196     }
197 
198     // Create and run the thread
199     res = pthread_create(&this->__thread_id, &__thread_attr, pthreadLauncher, this);
200     switch (res) {
201         case 0: // Success
202             break;
203         case EAGAIN:
204             std::cerr << "Thread creation failed: System doesn't allow to create another thread."
205                       << std::endl << std::flush;
206             RunningCondition.Set(false);
207             break;
208         case EPERM:
209             std::cerr << "Thread creation failed: You're lacking permisssions to set required scheduling policy and parameters."
210                       << std::endl << std::flush;
211             RunningCondition.Set(false);
212             break;
213         default:
214             std::cerr << "Thread creation failed: Unknown cause."
215                       << std::endl << std::flush;
216             RunningCondition.Set(false);
217             break;
218     }
219     return res;
220 #endif
221 }
222 
223 /**
224  *  Stops the thread synchronously. This method will block until the thread
225  *  actually stopped its execution before it will return from this method.
226  *
227  *  If the thread is not running when calling this method, this will be detected
228  *  and the call will be ignored. So it is safe to call this method both if the
229  *  thread never started, as well as if the thread has already been stopped. And
230  *  in fact you should explicitly call StopThread() before the Thread object is
231  *  going to be destructured!
232  *
233  *  @see SignalStopThread()
234  */
StopThread()235 int Thread::StopThread() {
236 #if defined(WIN32_SIGNALSTARTTHREAD_WORKAROUND)
237     SignalStopThread();
238     win32isRunning = false;
239     return 0;
240 #else
241     // LockGuard cannot be used here, because this is a bit more tricky here
242     RunningCondition.Lock();
243     #if !defined(WIN32)
244     // if thread was calling StopThread() on itself
245     if (pthread_equal(__thread_id, pthread_self())) {
246         RunningCondition.PreLockedSet(false);
247         state = DETACHED;
248         pthread_detach(__thread_id);
249         RunningCondition.Unlock();
250         pthread_exit(NULL);
251     }
252     #endif
253     // if we are here, then any other thread called StopThread() but not the thread itself
254     if (RunningCondition.GetUnsafe()) {
255         SignalStopThread();
256         // wait until thread stopped execution
257         RunningCondition.PreLockedWaitAndUnlockIf(true);
258         #if !defined(WIN32)
259         pthread_join(__thread_id, NULL);
260         #endif
261         RunningCondition.Lock();
262     }
263     // If the thread terminated on its own (i.e. returned from Main()) without
264     // any thread calling StopThread() yet, then the OS blocks termination of
265     // the thread waiting for a pthread_join() call. So we must detach the
266     // thread in this case, because otherwise it will cause a thread leak.
267     if (state == PENDING_JOIN) {
268         state = DETACHED;
269         #if !defined(WIN32)
270         pthread_detach(__thread_id);
271         #endif
272     }
273     RunningCondition.Unlock();
274     return 0;
275 #endif
276 }
277 
278 /**
279  *  Stops the thread asynchronously. This method will signal to stop the thread
280  *  and return immediately. Note that due to this the thread might still run
281  *  when this method returns!
282  *
283  *  @b IMPORTANT: You @ MUST still call StopThread() before destructing the
284  *  Thread object, even if you called SignalStopThread() before and the thread
285  *  is no longer running! Otherwise this may lead to a thread leak!
286  *
287  *  @see StopThread()
288  */
SignalStopThread()289 int Thread::SignalStopThread() {
290     //FIXME: segfaults when thread is not yet running
291 #if defined(WIN32)
292     BOOL res;
293     res = TerminateThread(hThread, 0); // we set ExitCode to 0
294     //res = WaitForSingleObject( hThread, INFINITE);
295     //myprint(("Thread::SignalStopThread:  WaitForSingleObject( hThread, INFINITE) res=%d\n",res));
296     #if defined(WIN32_SIGNALSTARTTHREAD_WORKAROUND)
297     win32isRunning = false;
298     #else
299     RunningCondition.Set(false);
300     #endif
301 #else
302     pthread_cancel(__thread_id);
303 #endif
304     return 0;
305 }
306 
307 /**
308  * Returns @c true in case the thread is currently running. This method does not
309  * block and returns immediately.
310  *
311  * Note that no synchronization is performed when calling this method. So the
312  * returned result is a very volatile information which must be processed with
313  * precautions, that is it may not be used for code that might cause a race
314  * condition.
315  */
IsRunning()316 bool Thread::IsRunning() {
317     #if defined(WIN32_SIGNALSTARTTHREAD_WORKAROUND)
318     return win32isRunning;
319     #else
320     return RunningCondition.GetUnsafe();
321     #endif
322 }
323 
324 /**
325  *  Sets the process SCHED_FIFO policy,  if max=1 then set at max priority,
326  *  else use min priority. delta is added to the priority so that we can
327  *  for example set 3 SCHED_FIFO tasks to different priorities by specifying
328  *  delta  0 , -1 , -2  ( 0 = highest priority because -1 is subtracted to the
329  *  current priority).
330  */
SetSchedulingPriority()331 int Thread::SetSchedulingPriority() {
332 #if defined(WIN32)
333     DWORD dwPriorityClass;
334     int nPriority;
335 
336     if(isRealTime) {
337         dwPriorityClass = REALTIME_PRIORITY_CLASS;
338         if (this->PriorityMax == 1) {
339             if(this->PriorityDelta == 0) nPriority = THREAD_PRIORITY_TIME_CRITICAL;
340             else nPriority = 7 + this->PriorityDelta;
341         }
342         else nPriority = THREAD_PRIORITY_NORMAL + this->PriorityDelta;
343     }
344     else {
345         dwPriorityClass = NORMAL_PRIORITY_CLASS;
346         nPriority = THREAD_PRIORITY_NORMAL + this->PriorityDelta;
347     }
348 
349     BOOL res;
350     // FIXME: priority class (realtime) does not work yet, gives error. check why.
351     #if 0
352     res = SetPriorityClass( hThread, dwPriorityClass );
353     if(res == false) {
354         std::cerr << "Thread: WARNING, setPriorityClass " << dwPriorityClass << "failed. Error " << GetLastError() << "\n";
355         return -1;
356     }
357 
358     res = SetThreadPriority( hThread, nPriority );
359     if(res == false) {
360         std::cerr << "Thread: WARNING, setThreadPriority " << nPriority << "failed. Error " << GetLastError() << "\n";
361         return -1;
362     }
363     #endif
364     return 0;
365 #else
366 #if !defined(__APPLE__)
367     int policy;
368     const char* policyDescription = NULL;
369     if (isRealTime) { // becomes a RT thread
370         policy = SCHED_FIFO;
371         policyDescription = "realtime";
372     } else { // 'normal', non-RT thread
373         policy = SCHED_OTHER;
374         policyDescription = "normal (non-RT)";
375     }
376     // set selected scheduling policy and priority
377     struct sched_param schp;
378     memset(&schp, 0, sizeof(schp));
379     if (isRealTime) { // it is not possible to change priority for the SCHED_OTHER policy
380         if (this->PriorityMax == 1) {
381             schp.sched_priority = sched_get_priority_max(policy) + this->PriorityDelta;
382         }
383         if (this->PriorityMax == -1) {
384             schp.sched_priority = sched_get_priority_min(policy) + this->PriorityDelta;
385         }
386     }
387     if (pthread_setschedparam(__thread_id, policy, &schp) != 0) {
388         std::cerr << "Thread: WARNING, can't assign "
389                   << policyDescription
390                   << " scheduling to thread!"
391                   << std::endl << std::flush;
392         return -1;
393     }
394 #endif
395     return 0;
396 #endif
397 }
398 
399 /**
400  * Locks the memory so it will not be swapped out by the operating system.
401  */
LockMemory()402 int Thread::LockMemory() {
403 #if defined(WIN32)
404     return 0;
405 #else
406 #if !defined(__APPLE__)
407     if (!bLockedMemory) return 0;
408     if (mlockall(MCL_CURRENT | MCL_FUTURE) < 0) {
409         std::cerr << "Thread: WARNING, can't mlockall() memory!\n"
410                   << std::flush;
411         return -1;
412     }
413 #endif
414     return 0;
415 #endif
416 }
417 
418 /**
419  *  Registers thread destructor callback function which will be executed when
420  *  the thread stops it's execution and sets the 'Running' flag to true. This
421  *  method will be called by the pthreadLauncher callback function, DO NOT
422  *  CALL THIS METHOD YOURSELF!
423  */
EnableDestructor()424 void Thread::EnableDestructor() {
425 #if defined(WIN32_SIGNALSTARTTHREAD_WORKAROUND)
426     win32isRunning = true;
427     return;
428 #endif
429     LockGuard g(RunningCondition);
430 #if !defined(WIN32)
431     pthread_key_create(&__thread_destructor_key, pthreadDestructor);
432     pthread_setspecific(__thread_destructor_key, this);
433 #endif
434     RunningCondition.PreLockedSet(true);
435 }
436 
437 /**
438  *  May be overridden by deriving classes to add additional custom cleanup
439  *  code if necessary for the event when thread terminates. Currently this
440  *  default implementation does nothing.
441  */
onThreadEnd()442 int Thread::onThreadEnd() {
443     return 0;
444 }
445 
TestCancel()446 void Thread::TestCancel() {
447 #if !defined(WIN32)
448     pthread_testcancel();
449 #endif
450 }
451 
452 #if defined(WIN32)
453 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)
454 // make sure stack is 16-byte aligned for SSE instructions
455 __attribute__((force_align_arg_pointer))
456 #endif
win32threadLauncher(LPVOID lpParameter)457 DWORD WINAPI Thread::win32threadLauncher(LPVOID lpParameter) {
458     Thread* t;
459     t = (Thread*) lpParameter;
460     t->SetSchedulingPriority();
461     t->LockMemory();
462     t->EnableDestructor();
463     t->Main();
464     return 0;
465 }
466 #else
467 /// Callback function for the POSIX thread API
pthreadLauncher(void * thread)468 void* Thread::pthreadLauncher(void* thread) {
469 #if !CONFIG_PTHREAD_TESTCANCEL
470     // let the thread be killable under any circumstances
471     if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
472         std::cerr << "Thread: WARNING, PTHREAD_CANCEL_ASYNCHRONOUS not supported!\n" << std::flush;
473     }
474 #endif
475     pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
476     Thread* t;
477     t = (Thread*) thread;
478     t->SetSchedulingPriority();
479     t->LockMemory();
480     t->EnableDestructor();
481     t->Main();
482     return NULL;
483 }
484 #endif
485 
486 #if !defined(WIN32)
487 /// Callback function for the POSIX thread API
pthreadDestructor(void * thread)488 void Thread::pthreadDestructor(void* thread) {
489     Thread* t;
490     t = (Thread*) thread;
491     LockGuard g(t->RunningCondition);
492     t->onThreadEnd();
493     pthread_key_delete(t->__thread_destructor_key);
494     // inform that thread termination blocks waiting for pthread_join()
495     // (not detaching the thread here already, because otherwise this might lead
496     // to a data race of the vpointer with the Thread object destructor)
497     t->state = PENDING_JOIN;
498     t->RunningCondition.PreLockedSet(false);
499 }
500 #endif
501 
502 /**
503  * Allow or prohibit whether the calling thread may be cancelled, remember its
504  * previous setting on a stack.
505  *
506  * @discussion The POSIX standard defines certaing system calls as implied
507  * thread cancellation points. For instance when a thread calls @c usleep(), the
508  * thread would immediately terminate if the thread was requested to be stopped.
509  * The problem with this is that a thread typically has critical sections where
510  * it may not simply terminate unexpectedly, e.g. if a thread is currently
511  * holding a mutex lock and then would call @c usleep() this may end up in a
512  * dead lock, since the lock would then never be unlocked again. For that reason
513  * a thread should first disable itself being cancelable before entering a
514  * critical section by calling @c pushCancelable(false) and it should
515  * re-enable thread cancelation by calling @c popCancelable() after having left
516  * the critical section(s). Refer to the following link for a list of functions
517  * being defined as implied cancelation points:
518  * http://man7.org/linux/man-pages/man7/pthreads.7.html
519  *
520  * @b NOTE: This method is currently not implemented for Windows yet!
521  *
522  * @param cancel - @c true: thread may be cancelled, @c false: thread may not
523  *                 be cancelled until re-enabled with either pushCancelable() or
524  *                 popCancelable()
525  * @see popCancelable() as counter part
526  */
pushCancelable(bool cancel)527 void Thread::pushCancelable(bool cancel) {
528     #if defined(WIN32)
529     //TODO: implementation for Windows
530     #else
531     int old;
532     pthread_setcancelstate(cancel ? PTHREAD_CANCEL_ENABLE : PTHREAD_CANCEL_DISABLE, &old);
533     cancelStates.push_back(old);
534     #endif
535 }
536 
537 /**
538  * Restore previous cancellation setting of calling thread by restoring it from
539  * stack.
540  *
541  * @b NOTE: This method is currently not implemented for Windows yet!
542  *
543  * @see pushCancelable() for details
544  */
popCancelable()545 void Thread::popCancelable() {
546     #if defined(WIN32)
547     //TODO: implementation for Windows
548     #else
549     int cancel = cancelStates.back();
550     cancelStates.pop_back();
551     pthread_setcancelstate(cancel ? PTHREAD_CANCEL_ENABLE : PTHREAD_CANCEL_DISABLE, NULL);
552     #endif
553 }
554 
555 /**
556  * Return this thread's name (intended just for debugging purposes).
557  *
558  * @b NOTE: This method is currently not implemented for Windows yet!
559  */
name()560 std::string Thread::name() {
561     #if defined(WIN32)
562     //TODO: implementation for Windows
563     return "not implemented";
564     #else
565     char buf[16] = {};
566     pthread_getname_np(__thread_id, buf, 16);
567     std::string s = buf;
568     if (s.empty())
569         s = "tid=" + ToString(__thread_id);
570     return s;
571     #endif
572 }
573 
574 /**
575  * Return calling thread's name (intended just for debugging purposes).
576  *
577  * @b NOTE: This method is currently not implemented for Windows yet!
578  */
nameOfCaller()579 std::string Thread::nameOfCaller() {
580     #if defined(WIN32)
581     //TODO: implementation for Windows
582     return "not implemented";
583     #else
584     char buf[16] = {};
585     pthread_getname_np(pthread_self(), buf, 16);
586     std::string s = buf;
587     if (s.empty())
588         s = "tid=" + ToString(pthread_self());
589     return s;
590     #endif
591 }
592 
593 /**
594  * Give calling thread a name (intended just for debugging purposes).
595  *
596  * @b NOTE: POSIX defines a limit of max. 16 characters for @a name.
597  *
598  * @b NOTE: This method is currently not implemented for Windows yet!
599  *
600  * @param name - arbitrary, i.e. human readable name for calling thread
601  */
setNameOfCaller(std::string name)602 void Thread::setNameOfCaller(std::string name) {
603     #if defined(WIN32)
604     //TODO: implementation for Windows
605     #elif __APPLE__
606     pthread_setname_np(name.c_str());
607     #else // Linux, NetBSD, FreeBSD, ...
608     pthread_setname_np(pthread_self(), name.c_str());
609     #endif
610 }
611 
612 } // namespace LinuxSampler
613