John Park | 33858a3 | 2018-09-28 23:05:48 -0700 | [diff] [blame] | 1 | #include "aos/util/thread.h" |
Brian Silverman | 798c778 | 2013-03-28 16:48:02 -0700 | [diff] [blame] | 2 | |
| 3 | #include <pthread.h> |
Brian Silverman | 325c597 | 2014-09-04 16:12:09 -0400 | [diff] [blame] | 4 | #include <signal.h> |
Brian Silverman | 653491d | 2014-05-13 16:53:29 -0700 | [diff] [blame] | 5 | |
John Park | 33858a3 | 2018-09-28 23:05:48 -0700 | [diff] [blame] | 6 | #include "aos/logging/logging.h" |
Brian Silverman | 798c778 | 2013-03-28 16:48:02 -0700 | [diff] [blame] | 7 | |
| 8 | namespace aos { |
| 9 | namespace util { |
| 10 | |
| 11 | Thread::Thread() : started_(false), joined_(false), should_terminate_(false) {} |
| 12 | |
| 13 | Thread::~Thread() { |
Austin Schuh | f257f3c | 2019-10-27 21:00:43 -0700 | [diff] [blame] | 14 | AOS_CHECK(!(started_ && !joined_)); |
Brian Silverman | 798c778 | 2013-03-28 16:48:02 -0700 | [diff] [blame] | 15 | } |
| 16 | |
| 17 | void Thread::Start() { |
Austin Schuh | f257f3c | 2019-10-27 21:00:43 -0700 | [diff] [blame] | 18 | AOS_CHECK(!started_); |
Brian Silverman | 798c778 | 2013-03-28 16:48:02 -0700 | [diff] [blame] | 19 | started_ = true; |
Austin Schuh | f257f3c | 2019-10-27 21:00:43 -0700 | [diff] [blame] | 20 | AOS_CHECK(pthread_create(&thread_, NULL, &Thread::StaticRun, this) == 0); |
Brian Silverman | 798c778 | 2013-03-28 16:48:02 -0700 | [diff] [blame] | 21 | } |
| 22 | |
| 23 | void Thread::Join() { |
Austin Schuh | f257f3c | 2019-10-27 21:00:43 -0700 | [diff] [blame] | 24 | AOS_CHECK(!joined_ && started_); |
Brian Silverman | 798c778 | 2013-03-28 16:48:02 -0700 | [diff] [blame] | 25 | joined_ = true; |
Brian Silverman | d4c4832 | 2014-09-06 21:17:29 -0400 | [diff] [blame] | 26 | should_terminate_.store(true); |
Austin Schuh | f257f3c | 2019-10-27 21:00:43 -0700 | [diff] [blame] | 27 | AOS_CHECK(pthread_join(thread_, NULL) == 0); |
Brian Silverman | 653491d | 2014-05-13 16:53:29 -0700 | [diff] [blame] | 28 | } |
| 29 | |
Brian Silverman | 325c597 | 2014-09-04 16:12:09 -0400 | [diff] [blame] | 30 | bool Thread::TryJoin() { |
Austin Schuh | f257f3c | 2019-10-27 21:00:43 -0700 | [diff] [blame] | 31 | AOS_CHECK(!joined_ && started_); |
Brian Silverman | 325c597 | 2014-09-04 16:12:09 -0400 | [diff] [blame] | 32 | #ifdef AOS_SANITIZER_thread |
| 33 | // ThreadSanitizer misses the tryjoin and then complains about leaking the |
| 34 | // thread. Instead, we'll just check if the thread is still around and then |
| 35 | // do a regular Join() iff it isn't. |
| 36 | // TODO(brians): Remove this once tsan learns about pthread_tryjoin_np. |
| 37 | const int kill_ret = pthread_kill(thread_, 0); |
| 38 | // If it's still around. |
| 39 | if (kill_ret == 0) return false; |
| 40 | // If it died, we'll get ESRCH. Otherwise, something went wrong. |
| 41 | if (kill_ret != ESRCH) { |
Austin Schuh | f257f3c | 2019-10-27 21:00:43 -0700 | [diff] [blame] | 42 | AOS_PELOG(FATAL, kill_ret, "pthread_kill(thread_, 0) failed"); |
Brian Silverman | 325c597 | 2014-09-04 16:12:09 -0400 | [diff] [blame] | 43 | } |
| 44 | Join(); |
| 45 | return true; |
| 46 | #else |
| 47 | const int ret = pthread_tryjoin_np(thread_, nullptr); |
| 48 | if (ret == 0) { |
| 49 | joined_ = true; |
| 50 | return true; |
| 51 | } else if (ret == EBUSY) { |
| 52 | return false; |
| 53 | } else { |
Austin Schuh | f257f3c | 2019-10-27 21:00:43 -0700 | [diff] [blame] | 54 | AOS_PELOG(FATAL, ret, "pthread_tryjoin_np(thread_, nullptr) failed"); |
Brian Silverman | 325c597 | 2014-09-04 16:12:09 -0400 | [diff] [blame] | 55 | } |
| 56 | #endif |
| 57 | } |
| 58 | |
| 59 | void Thread::RequestStop() { |
Austin Schuh | f257f3c | 2019-10-27 21:00:43 -0700 | [diff] [blame] | 60 | AOS_CHECK(!joined_ && started_); |
Brian Silverman | 325c597 | 2014-09-04 16:12:09 -0400 | [diff] [blame] | 61 | should_terminate_.store(true); |
| 62 | } |
| 63 | |
Brian Silverman | 653491d | 2014-05-13 16:53:29 -0700 | [diff] [blame] | 64 | void Thread::WaitUntilDone() { |
Austin Schuh | f257f3c | 2019-10-27 21:00:43 -0700 | [diff] [blame] | 65 | AOS_CHECK(!joined_ && started_); |
Brian Silverman | 653491d | 2014-05-13 16:53:29 -0700 | [diff] [blame] | 66 | joined_ = true; |
Austin Schuh | f257f3c | 2019-10-27 21:00:43 -0700 | [diff] [blame] | 67 | AOS_CHECK(pthread_join(thread_, NULL) == 0); |
Brian Silverman | 798c778 | 2013-03-28 16:48:02 -0700 | [diff] [blame] | 68 | } |
| 69 | |
| 70 | void *Thread::StaticRun(void *self) { |
| 71 | static_cast<Thread *>(self)->Run(); |
| 72 | return NULL; |
| 73 | } |
| 74 | |
| 75 | } // namespace util |
| 76 | } // namespace aos |