1 /* 2 * Copyright (C) 2015-2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "worker.h" 18 19 #include <sys/prctl.h> 20 #include <sys/resource.h> 21 22 namespace android { 23 24 Worker::Worker(const char *name, int priority) 25 : name_(name), priority_(priority), exit_(false), initialized_(false) { 26 } 27 28 Worker::~Worker() { 29 Exit(); 30 } 31 32 int Worker::InitWorker() { 33 std::lock_guard<std::mutex> lk(mutex_); 34 if (initialized()) 35 return -EALREADY; 36 37 thread_ = std::unique_ptr<std::thread>( 38 new std::thread(&Worker::InternalRoutine, this)); 39 initialized_ = true; 40 exit_ = false; 41 42 return 0; 43 } 44 45 void Worker::Exit() { 46 std::unique_lock<std::mutex> lk(mutex_); 47 exit_ = true; 48 if (initialized()) { 49 lk.unlock(); 50 cond_.notify_all(); 51 thread_->join(); 52 initialized_ = false; 53 } 54 } 55 56 int Worker::WaitForSignalOrExitLocked(int64_t max_nanoseconds) { 57 int ret = 0; 58 if (should_exit()) 59 return -EINTR; 60 61 std::unique_lock<std::mutex> lk(mutex_, std::adopt_lock); 62 if (max_nanoseconds < 0) { 63 cond_.wait(lk); 64 } else if (std::cv_status::timeout == 65 cond_.wait_for(lk, std::chrono::nanoseconds(max_nanoseconds))) { 66 ret = -ETIMEDOUT; 67 } 68 69 // exit takes precedence on timeout 70 if (should_exit()) 71 ret = -EINTR; 72 73 // release leaves mutex locked when going out of scope 74 lk.release(); 75 76 return ret; 77 } 78 79 void Worker::InternalRoutine() { 80 setpriority(PRIO_PROCESS, 0, priority_); 81 prctl(PR_SET_NAME, name_.c_str()); 82 83 std::unique_lock<std::mutex> lk(mutex_, std::defer_lock); 84 85 while (true) { 86 lk.lock(); 87 if (should_exit()) 88 return; 89 lk.unlock(); 90 91 Routine(); 92 } 93 } 94 } // namespace android 95