1 /*
2  * Copyright 2023 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 #pragma once
18 
19 #include <pthread.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 
23 #include <condition_variable>
24 #include <cstdint>
25 #include <mutex>
26 #include <queue>
27 #include <string>
28 
29 #include "osi/include/thread.h"
30 
31 using thread_func = std::function<void(void* context)>;
32 using thread_data = void*;
33 using work_item = std::pair<thread_func, thread_data>;
34 
35 class semaphore_t {
36   std::condition_variable condition_;
37   unsigned long count_ = 0;  // Initialized as locked.
38 
39  public:
40   std::mutex mutex_;
notify()41   void notify() {
42     std::lock_guard<decltype(mutex_)> lock(mutex_);
43     ++count_;
44     condition_.notify_one();
45   }
46 
wait()47   void wait() {
48     std::unique_lock<decltype(mutex_)> lock(mutex_);
49     while (!count_)  // Handle spurious wake-ups.
50       condition_.wait(lock);
51     --count_;
52   }
53 
try_wait()54   bool try_wait() {
55     std::lock_guard<decltype(mutex_)> lock(mutex_);
56     if (count_) {
57       --count_;
58       return true;
59     }
60     return false;
61   }
62 };
63 
64 struct thread_start_arg_t {
65   thread_t* thread;
66   int thread_id;
67   semaphore_t start_sem;
68 };
69 
70 struct thread_t {
71   enum class State {
72     STOPPED,
73     RUNNING,
74     QUIESCE,
75   };
76 
77  private:
78   State is_running_{State::STOPPED};
79   mutable std::mutex is_running_lock_;
80   semaphore_t thread_finish_semaphore;
81 
82  public:
83   std::queue<work_item> work_queue;
84   semaphore_t work_queue_semaphore;
85 
86   bool is_running() const;
87   void set_state(State state);
88   void quiesce();
89   void notify_finished();
90 
91   pthread_t pthread_;
92   pid_t tid_;
93   std::string name_;
94 };
95