1 /*
2 * barrier -- mouse and keyboard sharing utility
3 * Copyright (C) 2012-2016 Symless Ltd.
4 * Copyright (C) 2002 Chris Schoeneman
5 *
6 * This package is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * found in the file LICENSE that should have accompanied this file.
9 *
10 * This package is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "arch/unix/ArchMultithreadPosix.h"
20
21 #include "arch/Arch.h"
22 #include "arch/XArch.h"
23
24 #include <signal.h>
25 #if TIME_WITH_SYS_TIME
26 # include <sys/time.h>
27 # include <time.h>
28 #else
29 # if HAVE_SYS_TIME_H
30 # include <sys/time.h>
31 # else
32 # include <time.h>
33 # endif
34 #endif
35 #include <cerrno>
36
37 #define SIGWAKEUP SIGUSR1
38
39 static
40 void
setSignalSet(sigset_t * sigset)41 setSignalSet(sigset_t* sigset)
42 {
43 sigemptyset(sigset);
44 sigaddset(sigset, SIGHUP);
45 sigaddset(sigset, SIGINT);
46 sigaddset(sigset, SIGTERM);
47 sigaddset(sigset, SIGUSR2);
48 }
49
50 //
51 // ArchThreadImpl
52 //
53
54 class ArchThreadImpl {
55 public:
56 ArchThreadImpl();
57
58 public:
59 int m_refCount;
60 IArchMultithread::ThreadID m_id;
61 pthread_t m_thread;
62 IArchMultithread::ThreadFunc m_func;
63 void* m_userData;
64 bool m_cancel;
65 bool m_cancelling;
66 bool m_exited;
67 void* m_result;
68 void* m_networkData;
69 };
70
ArchThreadImpl()71 ArchThreadImpl::ArchThreadImpl() :
72 m_refCount(1),
73 m_id(0),
74 m_func(NULL),
75 m_userData(NULL),
76 m_cancel(false),
77 m_cancelling(false),
78 m_exited(false),
79 m_result(NULL),
80 m_networkData(NULL)
81 {
82 // do nothing
83 }
84
85
86 //
87 // ArchMultithreadPosix
88 //
89
90 ArchMultithreadPosix* ArchMultithreadPosix::s_instance = NULL;
91
ArchMultithreadPosix()92 ArchMultithreadPosix::ArchMultithreadPosix() :
93 m_newThreadCalled(false),
94 m_nextID(0)
95 {
96 assert(s_instance == NULL);
97
98 s_instance = this;
99
100 // no signal handlers
101 for (size_t i = 0; i < kNUM_SIGNALS; ++i) {
102 m_signalFunc[i] = NULL;
103 m_signalUserData[i] = NULL;
104 }
105
106 // create thread for calling (main) thread and add it to our
107 // list. no need to lock the mutex since we're the only thread.
108 m_mainThread = new ArchThreadImpl;
109 m_mainThread->m_thread = pthread_self();
110 insert(m_mainThread);
111
112 // install SIGWAKEUP handler. this causes SIGWAKEUP to interrupt
113 // system calls. we use that when cancelling a thread to force it
114 // to wake up immediately if it's blocked in a system call. we
115 // won't need this until another thread is created but it's fine
116 // to install it now.
117 struct sigaction act;
118 sigemptyset(&act.sa_mask);
119 # if defined(SA_INTERRUPT)
120 act.sa_flags = SA_INTERRUPT;
121 # else
122 act.sa_flags = 0;
123 # endif
124 act.sa_handler = &threadCancel;
125 sigaction(SIGWAKEUP, &act, NULL);
126
127 // set desired signal dispositions. let SIGWAKEUP through but
128 // ignore SIGPIPE (we'll handle EPIPE).
129 sigset_t sigset;
130 sigemptyset(&sigset);
131 sigaddset(&sigset, SIGWAKEUP);
132 pthread_sigmask(SIG_UNBLOCK, &sigset, NULL);
133 sigemptyset(&sigset);
134 sigaddset(&sigset, SIGPIPE);
135 pthread_sigmask(SIG_BLOCK, &sigset, NULL);
136 }
137
~ArchMultithreadPosix()138 ArchMultithreadPosix::~ArchMultithreadPosix()
139 {
140 assert(s_instance != NULL);
141
142 s_instance = NULL;
143 }
144
145 void
setNetworkDataForCurrentThread(void * data)146 ArchMultithreadPosix::setNetworkDataForCurrentThread(void* data)
147 {
148 std::lock_guard<std::mutex> lock(m_threadMutex);
149 ArchThreadImpl* thread = find(pthread_self());
150 thread->m_networkData = data;
151 }
152
153 void*
getNetworkDataForThread(ArchThread thread)154 ArchMultithreadPosix::getNetworkDataForThread(ArchThread thread)
155 {
156 std::lock_guard<std::mutex> lock(m_threadMutex);
157 return thread->m_networkData;
158 }
159
160 ArchMultithreadPosix*
getInstance()161 ArchMultithreadPosix::getInstance()
162 {
163 return s_instance;
164 }
165
166 ArchCond
newCondVar()167 ArchMultithreadPosix::newCondVar()
168 {
169 ArchCondImpl* cond = new ArchCondImpl;
170 int status = pthread_cond_init(&cond->m_cond, NULL);
171 (void)status;
172 assert(status == 0);
173 return cond;
174 }
175
176 void
closeCondVar(ArchCond cond)177 ArchMultithreadPosix::closeCondVar(ArchCond cond)
178 {
179 int status = pthread_cond_destroy(&cond->m_cond);
180 (void)status;
181 assert(status == 0);
182 delete cond;
183 }
184
185 void
signalCondVar(ArchCond cond)186 ArchMultithreadPosix::signalCondVar(ArchCond cond)
187 {
188 int status = pthread_cond_signal(&cond->m_cond);
189 (void)status;
190 assert(status == 0);
191 }
192
193 void
broadcastCondVar(ArchCond cond)194 ArchMultithreadPosix::broadcastCondVar(ArchCond cond)
195 {
196 int status = pthread_cond_broadcast(&cond->m_cond);
197 (void)status;
198 assert(status == 0);
199 }
200
201 bool
waitCondVar(ArchCond cond,ArchMutex mutex,double timeout)202 ArchMultithreadPosix::waitCondVar(ArchCond cond,
203 ArchMutex mutex, double timeout)
204 {
205 // we can't wait on a condition variable and also wake it up for
206 // cancellation since we don't use posix cancellation. so we
207 // must wake up periodically to check for cancellation. we
208 // can't simply go back to waiting after the check since the
209 // condition may have changed and we'll have lost the signal.
210 // so we have to return to the caller. since the caller will
211 // always check for spurious wakeups the only drawback here is
212 // performance: we're waking up a lot more than desired.
213 static const double maxCancellationLatency = 0.1;
214 if (timeout < 0.0 || timeout > maxCancellationLatency) {
215 timeout = maxCancellationLatency;
216 }
217
218 // see if we should cancel this thread
219 testCancelThread();
220
221 // get final time
222 struct timeval now;
223 gettimeofday(&now, NULL);
224 struct timespec finalTime;
225 finalTime.tv_sec = now.tv_sec;
226 finalTime.tv_nsec = now.tv_usec * 1000;
227 long timeout_sec = (long)timeout;
228 long timeout_nsec = (long)(1.0e+9 * (timeout - timeout_sec));
229 finalTime.tv_sec += timeout_sec;
230 finalTime.tv_nsec += timeout_nsec;
231 if (finalTime.tv_nsec >= 1000000000) {
232 finalTime.tv_nsec -= 1000000000;
233 finalTime.tv_sec += 1;
234 }
235
236 // wait
237 int status = pthread_cond_timedwait(&cond->m_cond,
238 &mutex->m_mutex, &finalTime);
239
240 // check for cancel again
241 testCancelThread();
242
243 switch (status) {
244 case 0:
245 // success
246 return true;
247
248 case ETIMEDOUT:
249 return false;
250
251 default:
252 assert(0 && "condition variable wait error");
253 return false;
254 }
255 }
256
257 ArchMutex
newMutex()258 ArchMultithreadPosix::newMutex()
259 {
260 pthread_mutexattr_t attr;
261 int status = pthread_mutexattr_init(&attr);
262 assert(status == 0);
263 ArchMutexImpl* mutex = new ArchMutexImpl;
264 status = pthread_mutex_init(&mutex->m_mutex, &attr);
265 assert(status == 0);
266 return mutex;
267 }
268
269 void
closeMutex(ArchMutex mutex)270 ArchMultithreadPosix::closeMutex(ArchMutex mutex)
271 {
272 int status = pthread_mutex_destroy(&mutex->m_mutex);
273 (void)status;
274 assert(status == 0);
275 delete mutex;
276 }
277
278 void
lockMutex(ArchMutex mutex)279 ArchMultithreadPosix::lockMutex(ArchMutex mutex)
280 {
281 int status = pthread_mutex_lock(&mutex->m_mutex);
282
283 switch (status) {
284 case 0:
285 // success
286 return;
287
288 case EDEADLK:
289 assert(0 && "lock already owned");
290 break;
291
292 case EAGAIN:
293 assert(0 && "too many recursive locks");
294 break;
295
296 default:
297 assert(0 && "unexpected error");
298 break;
299 }
300 }
301
302 void
unlockMutex(ArchMutex mutex)303 ArchMultithreadPosix::unlockMutex(ArchMutex mutex)
304 {
305 int status = pthread_mutex_unlock(&mutex->m_mutex);
306
307 switch (status) {
308 case 0:
309 // success
310 return;
311
312 case EPERM:
313 assert(0 && "thread doesn't own a lock");
314 break;
315
316 default:
317 assert(0 && "unexpected error");
318 break;
319 }
320 }
321
322 ArchThread
newThread(ThreadFunc func,void * data)323 ArchMultithreadPosix::newThread(ThreadFunc func, void* data)
324 {
325 assert(func != NULL);
326
327 // initialize signal handler. we do this here instead of the
328 // constructor so we can avoid daemonizing (using fork())
329 // when there are multiple threads. clients can safely
330 // use condition variables and mutexes before creating a
331 // new thread and they can safely use the only thread
332 // they have access to, the main thread, so they really
333 // can't tell the difference.
334 if (!m_newThreadCalled) {
335 m_newThreadCalled = true;
336 startSignalHandler();
337 }
338
339 // note that the child thread will wait until we release this mutex
340 std::lock_guard<std::mutex> lock(m_threadMutex);
341
342 // create thread impl for new thread
343 ArchThreadImpl* thread = new ArchThreadImpl;
344 thread->m_func = func;
345 thread->m_userData = data;
346
347 // create the thread. pthread_create() on RedHat 7.2 smp fails
348 // if passed a NULL attr so use a default attr.
349 pthread_attr_t attr;
350 int status = pthread_attr_init(&attr);
351 if (status == 0) {
352 status = pthread_create(&thread->m_thread, &attr,
353 &ArchMultithreadPosix::threadFunc, thread);
354 pthread_attr_destroy(&attr);
355 }
356
357 // check if thread was started
358 if (status != 0) {
359 // failed to start thread so clean up
360 delete thread;
361 thread = NULL;
362 }
363 else {
364 // add thread to list
365 insert(thread);
366
367 // increment ref count to account for the thread itself
368 refThread(thread);
369 }
370
371 return thread;
372 }
373
374 ArchThread
newCurrentThread()375 ArchMultithreadPosix::newCurrentThread()
376 {
377 std::lock_guard<std::mutex> lock(m_threadMutex);
378
379 ArchThreadImpl* thread = find(pthread_self());
380 assert(thread != NULL);
381 return thread;
382 }
383
384 void
closeThread(ArchThread thread)385 ArchMultithreadPosix::closeThread(ArchThread thread)
386 {
387 assert(thread != NULL);
388
389 // decrement ref count and clean up thread if no more references
390 if (--thread->m_refCount == 0) {
391 // detach from thread (unless it's the main thread)
392 if (thread->m_func != NULL) {
393 pthread_detach(thread->m_thread);
394 }
395
396 // remove thread from list
397 {
398 std::lock_guard<std::mutex> lock(m_threadMutex);
399 assert(findNoRef(thread->m_thread) == thread);
400 erase(thread);
401 }
402
403 // done with thread
404 delete thread;
405 }
406 }
407
408 ArchThread
copyThread(ArchThread thread)409 ArchMultithreadPosix::copyThread(ArchThread thread)
410 {
411 refThread(thread);
412 return thread;
413 }
414
415 void
cancelThread(ArchThread thread)416 ArchMultithreadPosix::cancelThread(ArchThread thread)
417 {
418 assert(thread != NULL);
419
420 // set cancel and wakeup flags if thread can be cancelled
421 bool wakeup = false;
422
423 {
424 std::lock_guard<std::mutex> lock(m_threadMutex);
425 if (!thread->m_exited && !thread->m_cancelling) {
426 thread->m_cancel = true;
427 wakeup = true;
428 }
429 }
430
431 // force thread to exit system calls if wakeup is true
432 if (wakeup) {
433 pthread_kill(thread->m_thread, SIGWAKEUP);
434 }
435 }
436
437 void
setPriorityOfThread(ArchThread thread,int)438 ArchMultithreadPosix::setPriorityOfThread(ArchThread thread, int /*n*/)
439 {
440 assert(thread != NULL);
441
442 // FIXME
443 }
444
445 void
testCancelThread()446 ArchMultithreadPosix::testCancelThread()
447 {
448 // find current thread
449 ArchThreadImpl* thread = nullptr;
450 {
451 std::lock_guard<std::mutex> lock(m_threadMutex);
452 thread = findNoRef(pthread_self());
453 }
454
455 // test cancel on thread
456 testCancelThreadImpl(thread);
457 }
458
459 bool
wait(ArchThread target,double timeout)460 ArchMultithreadPosix::wait(ArchThread target, double timeout)
461 {
462 assert(target != NULL);
463
464 ArchThreadImpl* self = nullptr;
465
466 {
467 std::lock_guard<std::mutex> lock(m_threadMutex);
468
469 // find current thread
470 self = findNoRef(pthread_self());
471
472 // ignore wait if trying to wait on ourself
473 if (target == self) {
474 return false;
475 }
476
477 // ref the target so it can't go away while we're watching it
478 refThread(target);
479 }
480
481 try {
482 // do first test regardless of timeout
483 testCancelThreadImpl(self);
484 if (isExitedThread(target)) {
485 closeThread(target);
486 return true;
487 }
488
489 // wait and repeat test if there's a timeout
490 if (timeout != 0.0) {
491 const double start = ARCH->time();
492 do {
493 // wait a little
494 ARCH->sleep(0.05);
495
496 // repeat test
497 testCancelThreadImpl(self);
498 if (isExitedThread(target)) {
499 closeThread(target);
500 return true;
501 }
502
503 // repeat wait and test until timed out
504 } while (timeout < 0.0 || (ARCH->time() - start) <= timeout);
505 }
506
507 closeThread(target);
508 return false;
509 }
510 catch (...) {
511 closeThread(target);
512 throw;
513 }
514 }
515
516 bool
isSameThread(ArchThread thread1,ArchThread thread2)517 ArchMultithreadPosix::isSameThread(ArchThread thread1, ArchThread thread2)
518 {
519 return (thread1 == thread2);
520 }
521
522 bool
isExitedThread(ArchThread thread)523 ArchMultithreadPosix::isExitedThread(ArchThread thread)
524 {
525 std::lock_guard<std::mutex> lock(m_threadMutex);
526 return thread->m_exited;
527 }
528
529 void*
getResultOfThread(ArchThread thread)530 ArchMultithreadPosix::getResultOfThread(ArchThread thread)
531 {
532 std::lock_guard<std::mutex> lock(m_threadMutex);
533 return thread->m_result;
534 }
535
536 IArchMultithread::ThreadID
getIDOfThread(ArchThread thread)537 ArchMultithreadPosix::getIDOfThread(ArchThread thread)
538 {
539 return thread->m_id;
540 }
541
542 void
setSignalHandler(ESignal signal,SignalFunc func,void * userData)543 ArchMultithreadPosix::setSignalHandler(
544 ESignal signal, SignalFunc func, void* userData)
545 {
546 std::lock_guard<std::mutex> lock(m_threadMutex);
547 m_signalFunc[signal] = func;
548 m_signalUserData[signal] = userData;
549 }
550
551 void
raiseSignal(ESignal signal)552 ArchMultithreadPosix::raiseSignal(ESignal signal)
553 {
554 std::lock_guard<std::mutex> lock(m_threadMutex);
555 if (m_signalFunc[signal] != NULL) {
556 m_signalFunc[signal](signal, m_signalUserData[signal]);
557 pthread_kill(m_mainThread->m_thread, SIGWAKEUP);
558 }
559 else if (signal == kINTERRUPT || signal == kTERMINATE) {
560 ARCH->cancelThread(m_mainThread);
561 }
562 }
563
564 void
startSignalHandler()565 ArchMultithreadPosix::startSignalHandler()
566 {
567 // set signal mask. the main thread blocks these signals and
568 // the signal handler thread will listen for them.
569 sigset_t sigset, oldsigset;
570 setSignalSet(&sigset);
571 pthread_sigmask(SIG_BLOCK, &sigset, &oldsigset);
572
573 // fire up the INT and TERM signal handler thread. we could
574 // instead arrange to catch and handle these signals but
575 // we'd be unable to cancel the main thread since no pthread
576 // calls are allowed in a signal handler.
577 pthread_attr_t attr;
578 int status = pthread_attr_init(&attr);
579 if (status == 0) {
580 status = pthread_create(&m_signalThread, &attr,
581 &ArchMultithreadPosix::threadSignalHandler,
582 NULL);
583 pthread_attr_destroy(&attr);
584 }
585 if (status != 0) {
586 // can't create thread to wait for signal so don't block
587 // the signals.
588 pthread_sigmask(SIG_UNBLOCK, &oldsigset, NULL);
589 }
590 }
591
592 ArchThreadImpl*
find(pthread_t thread)593 ArchMultithreadPosix::find(pthread_t thread)
594 {
595 ArchThreadImpl* impl = findNoRef(thread);
596 if (impl != NULL) {
597 refThread(impl);
598 }
599 return impl;
600 }
601
602 ArchThreadImpl*
findNoRef(pthread_t thread)603 ArchMultithreadPosix::findNoRef(pthread_t thread)
604 {
605 // linear search
606 for (ThreadList::const_iterator index = m_threadList.begin();
607 index != m_threadList.end(); ++index) {
608 if ((*index)->m_thread == thread) {
609 return *index;
610 }
611 }
612 return NULL;
613 }
614
615 void
insert(ArchThreadImpl * thread)616 ArchMultithreadPosix::insert(ArchThreadImpl* thread)
617 {
618 assert(thread != NULL);
619
620 // thread shouldn't already be on the list
621 assert(findNoRef(thread->m_thread) == NULL);
622
623 // set thread id. note that we don't worry about m_nextID
624 // wrapping back to 0 and duplicating thread ID's since the
625 // likelihood of barrier running that long is vanishingly
626 // small.
627 thread->m_id = ++m_nextID;
628
629 // append to list
630 m_threadList.push_back(thread);
631 }
632
633 void
erase(ArchThreadImpl * thread)634 ArchMultithreadPosix::erase(ArchThreadImpl* thread)
635 {
636 for (ThreadList::iterator index = m_threadList.begin();
637 index != m_threadList.end(); ++index) {
638 if (*index == thread) {
639 m_threadList.erase(index);
640 break;
641 }
642 }
643 }
644
645 void
refThread(ArchThreadImpl * thread)646 ArchMultithreadPosix::refThread(ArchThreadImpl* thread)
647 {
648 assert(thread != NULL);
649 assert(findNoRef(thread->m_thread) != NULL);
650 ++thread->m_refCount;
651 }
652
653 void
testCancelThreadImpl(ArchThreadImpl * thread)654 ArchMultithreadPosix::testCancelThreadImpl(ArchThreadImpl* thread)
655 {
656 assert(thread != NULL);
657
658 std::lock_guard<std::mutex> lock(m_threadMutex);
659
660 // update cancel state
661 bool cancel = false;
662 if (thread->m_cancel && !thread->m_cancelling) {
663 thread->m_cancelling = true;
664 thread->m_cancel = false;
665 cancel = true;
666 }
667
668 // unwind thread's stack if cancelling
669 if (cancel) {
670 throw XThreadCancel();
671 }
672 }
673
674 void*
threadFunc(void * vrep)675 ArchMultithreadPosix::threadFunc(void* vrep)
676 {
677 // get the thread
678 ArchThreadImpl* thread = static_cast<ArchThreadImpl*>(vrep);
679
680 // setup pthreads
681 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
682 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
683
684 // run thread
685 s_instance->doThreadFunc(thread);
686
687 // terminate the thread
688 return NULL;
689 }
690
691 void
doThreadFunc(ArchThread thread)692 ArchMultithreadPosix::doThreadFunc(ArchThread thread)
693 {
694 // default priority is slightly below normal
695 setPriorityOfThread(thread, 1);
696
697 // wait for parent to initialize this object
698 {
699 std::lock_guard<std::mutex> lock(m_threadMutex);
700 }
701
702 void* result = NULL;
703 try {
704 // go
705 result = (*thread->m_func)(thread->m_userData);
706 }
707
708 catch (XThreadCancel&) {
709 // client called cancel()
710 }
711 catch (...) {
712 // note -- don't catch (...) to avoid masking bugs
713 {
714 std::lock_guard<std::mutex> lock(m_threadMutex);
715 thread->m_exited = true;
716 }
717 closeThread(thread);
718 throw;
719 }
720
721 // thread has exited
722 {
723 std::lock_guard<std::mutex> lock(m_threadMutex);
724 thread->m_result = result;
725 thread->m_exited = true;
726 }
727
728 // done with thread
729 closeThread(thread);
730 }
731
732 void
threadCancel(int)733 ArchMultithreadPosix::threadCancel(int)
734 {
735 // do nothing
736 }
737
738 void*
threadSignalHandler(void *)739 ArchMultithreadPosix::threadSignalHandler(void*)
740 {
741 // detach
742 pthread_detach(pthread_self());
743
744 // add signal to mask
745 sigset_t sigset;
746 setSignalSet(&sigset);
747
748 // also wait on SIGABRT. on linux (others?) this thread (process)
749 // will persist after all the other threads evaporate due to an
750 // assert unless we wait on SIGABRT. that means our resources (like
751 // the socket we're listening on) are not released and never will be
752 // until the lingering thread is killed. i don't know why sigwait()
753 // should protect the thread from being killed. note that sigwait()
754 // doesn't actually return if we receive SIGABRT and, for some
755 // reason, we don't have to block SIGABRT.
756 sigaddset(&sigset, SIGABRT);
757
758 // we exit the loop via thread cancellation in sigwait()
759 for (;;) {
760 // wait
761 #if HAVE_POSIX_SIGWAIT
762 int signal = 0;
763 sigwait(&sigset, &signal);
764 #else
765 sigwait(&sigset);
766 #endif
767
768 // if we get here then the signal was raised
769 switch (signal) {
770 case SIGINT:
771 ARCH->raiseSignal(kINTERRUPT);
772 break;
773
774 case SIGTERM:
775 ARCH->raiseSignal(kTERMINATE);
776 break;
777
778 case SIGHUP:
779 ARCH->raiseSignal(kHANGUP);
780 break;
781
782 case SIGUSR2:
783 ARCH->raiseSignal(kUSER);
784 break;
785
786 default:
787 // ignore
788 break;
789 }
790 }
791
792 return NULL;
793 }
794