1 /*
2 * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #define HST_LOG_TAG "Thread"
17
18 #include "osal/task/thread.h"
19 #include "common/log.h"
20 #include "osal/task/autolock.h"
21
22 namespace OHOS {
23 namespace Media {
Thread(ThreadPriority priority)24 Thread::Thread(ThreadPriority priority) noexcept : id_(), name_(), priority_(priority), state_()
25 {
26 }
27
Thread(Thread && other)28 Thread::Thread(Thread&& other) noexcept
29 {
30 *this = std::move(other);
31 }
32
operator =(Thread && other)33 Thread& Thread::operator=(Thread&& other) noexcept
34 {
35 if (this != &other) {
36 AutoLock lock(mutex_);
37 id_ = other.id_;
38 name_ = std::move(other.name_);
39 priority_ = other.priority_;
40 state_ = std::move(other.state_);
41 }
42 return *this;
43 }
44
~Thread()45 Thread::~Thread() noexcept
46 {
47 if (isExistThread_.load()) {
48 pthread_join(id_, nullptr);
49 }
50 }
51
HasThread() const52 bool Thread::HasThread() const noexcept
53 {
54 AutoLock lock(mutex_);
55 return state_ != nullptr;
56 }
57
SetName(const std::string & name)58 void Thread::SetName(const std::string& name)
59 {
60 name_ = name;
61 }
62
CreateThread(const std::function<void ()> & func)63 bool Thread::CreateThread(const std::function<void()>& func)
64 {
65 {
66 AutoLock lock(mutex_);
67 state_ = std::make_unique<State>();
68 state_->func = func;
69 state_->name = name_;
70 }
71 pthread_attr_t attr;
72 pthread_attr_init(&attr);
73 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
74 #ifdef OHOS_LITE
75 // Only OHOS_LITE can set inheritsched and schedpolicy.
76 pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
77 pthread_attr_setschedpolicy(&attr, SCHED_RR);
78 #endif
79 struct sched_param sched = {static_cast<int>(priority_)};
80 pthread_attr_setschedparam(&attr, &sched);
81 #if defined(THREAD_STACK_SIZE) and THREAD_STACK_SIZE > 0
82 pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE);
83 MEDIA_LOG_I("thread stack size set to " PUBLIC_LOG_D32, THREAD_STACK_SIZE);
84 #endif
85 int rtv = pthread_create(&id_, &attr, Thread::Run, this);
86 if (rtv == 0) {
87 MEDIA_LOG_I("thread " PUBLIC_LOG_S " create success", name_.c_str());
88 isExistThread_.store(true);
89 SetNameInternal();
90 } else {
91 AutoLock lock(mutex_);
92 if (state_ != nullptr) {
93 state_.reset();
94 }
95 MEDIA_LOG_E("thread create failed, name: " PUBLIC_LOG_S ", rtv: " PUBLIC_LOG_D32, name_.c_str(), rtv);
96 }
97 return rtv == 0;
98 }
99
IsRunningInSelf()100 bool Thread::IsRunningInSelf()
101 {
102 pthread_t tid = pthread_self();
103 AutoLock lock(mutex_);
104 return tid == id_;
105 }
106
SetNameInternal()107 void Thread::SetNameInternal()
108 {
109 AutoLock lock(mutex_);
110 if (state_ && !name_.empty()) {
111 constexpr int threadNameMaxSize = 15;
112 if (name_.size() > threadNameMaxSize) {
113 MEDIA_LOG_W("task name " PUBLIC_LOG_S " exceed max size: " PUBLIC_LOG_D32,
114 name_.c_str(), threadNameMaxSize);
115 name_ = name_.substr(0, threadNameMaxSize);
116 }
117 pthread_setname_np(id_, name_.c_str());
118 }
119 }
120
Run(void * arg)121 void* Thread::Run(void* arg) // NOLINT: void*
122 {
123 std::function<void()> func;
124 std::string name;
125 {
126 auto currentThread = static_cast<Thread *>(arg);
127 AutoLock lock(currentThread->mutex_);
128 auto state = currentThread->state_.get();
129 if (state == nullptr) {
130 return nullptr;
131 }
132 func = state->func;
133 name = state->name;
134 }
135 func();
136 {
137 auto currentThread = static_cast<Thread *>(arg);
138 AutoLock lock(currentThread->mutex_);
139 currentThread->state_ = nullptr;
140 }
141 MEDIA_LOG_W("Thread " PUBLIC_LOG_S " exited...", name.c_str());
142 return nullptr;
143 }
144 } // namespace Media
145 } // namespace OHOS
146