2 * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "launchpad/thread_control.hh"
19 #include <sys/types.h>
26 #include "launchpad/log_private.hh"
31 const int SIGRTINT = SIGRTMIN + 2;
33 std::vector<pid_t> GetTasks() {
34 std::vector<pid_t> tasks;
35 std::filesystem::path task_path("/proc/self/task");
37 for (auto& entry : std::filesystem::directory_iterator(task_path)) {
38 if (!std::isdigit(entry.path().filename().c_str()[0]))
41 tasks.push_back(std::stoi(entry.path().filename().string()));
43 } catch (const std::filesystem::filesystem_error& e) {
44 _E("Exception occurs. error: %s", e.what());
52 ThreadControl& ThreadControl::GetInst() {
53 static ThreadControl inst;
57 ThreadControl::~ThreadControl() {
61 int ThreadControl::BlockThreads() {
65 if (!ChangeSigaction())
74 int ThreadControl::UnblockThreads() {
85 bool ThreadControl::IsBlocked() const {
89 int ThreadControl::GetCount() {
90 return GetTasks().size();
93 bool ThreadControl::ChangeSigaction() {
95 memset(&act, '\0', sizeof(struct sigaction));
96 sigemptyset(&act.sa_mask);
97 act.sa_flags = SA_RESTART | SA_SIGINFO;
98 act.sa_handler = SignalHandler;
100 if (sigaction(SIGRTINT, &act, &old_action_) != 0) {
101 _E("sigaction() is failed. errno(%d)", errno);
108 void ThreadControl::InterruptThreads() {
109 pid_t pid = getpid();
110 auto tasks = GetTasks();
111 count_ = tasks.size() - 1;
112 _D("tasks count: %d", count_);
113 for (auto& tid : tasks) {
115 _D("Send signal to thread(%d)", tid);
116 if (tgkill(pid, tid, SIGRTINT) != 0) {
117 _E("tgkill() is failed. tid(%d), errno(%d)", tid, errno);
124 void ThreadControl::ContinueThreads() {
125 std::unique_lock<std::mutex> lock(mutex_);
126 count_ = GetTasks().size() - 1;
127 _D("tasks count: %d", count_);
132 void ThreadControl::WaitThreads() {
133 for (int i = 1000; count_ && i; --i)
137 void ThreadControl::RestoreSigaction() {
138 if (sigaction(SIGRTINT, &old_action_, nullptr) != 0)
139 _E("sigaction() is failed. errno(%d)", errno);
142 void ThreadControl::SignalHandler(int signo) {
144 auto& inst = ThreadControl::GetInst();
145 std::unique_lock<std::mutex> lock(inst.mutex_);
147 inst.cond_.wait(lock, [&] { return inst.done_; });
152 } // namespace launchpad