• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "qos.h"
23 #include "res_type.h"
24 #include "res_sched_client.h"
25 
26 namespace {
27 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_FOUNDATION, "Thread" };
28 constexpr uint32_t RES_TYPE = OHOS::ResourceSchedule::ResType::RES_TYPE_THREAD_QOS_CHANGE;
29 constexpr int64_t RES_VALUE = 0;
30 }
31 
32 namespace OHOS {
33 namespace Media {
Thread(ThreadPriority priority)34 Thread::Thread(ThreadPriority priority) noexcept : id_(), name_(), priority_(priority), state_()
35 {
36 }
37 
Thread(Thread && other)38 Thread::Thread(Thread&& other) noexcept
39 {
40     *this = std::move(other);
41 }
42 
operator =(Thread && other)43 Thread& Thread::operator=(Thread&& other) noexcept
44 {
45     if (this != &other) {
46         AutoLock lock(mutex_);
47         id_ = other.id_;
48         name_ = std::move(other.name_);
49         priority_ = other.priority_;
50         state_ = std::move(other.state_);
51     }
52     return *this;
53 }
54 
~Thread()55 Thread::~Thread() noexcept
56 {
57     if (isExistThread_.load()) {
58         pthread_join(id_, nullptr);
59     }
60 }
61 
HasThread() const62 bool Thread::HasThread() const noexcept
63 {
64     AutoLock lock(mutex_);
65     return state_ != nullptr;
66 }
67 
SetName(const std::string & name)68 void Thread::SetName(const std::string& name)
69 {
70     name_ = name;
71 }
72 
CreateThread(const std::function<void ()> & func)73 bool Thread::CreateThread(const std::function<void()>& func)
74 {
75     {
76         AutoLock lock(mutex_);
77         state_ = std::make_unique<State>();
78         state_->func = func;
79         state_->name = name_;
80     }
81     pthread_attr_t attr;
82     pthread_attr_init(&attr);
83     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
84 #ifdef OHOS_LITE
85     // Only OHOS_LITE can set inheritsched and schedpolicy.
86     pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
87     pthread_attr_setschedpolicy(&attr, SCHED_RR);
88 #endif
89     struct sched_param sched = {static_cast<int>(priority_)};
90     pthread_attr_setschedparam(&attr, &sched);
91 #if defined(THREAD_STACK_SIZE) and THREAD_STACK_SIZE > 0
92     pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE);
93     MEDIA_LOG_I("thread stack size set to " PUBLIC_LOG_D32, THREAD_STACK_SIZE);
94 #endif
95     int rtv = pthread_create(&id_, &attr, Thread::Run, this);
96     if (rtv == 0) {
97         MEDIA_LOG_I("thread " PUBLIC_LOG_S " create success", name_.c_str());
98         isExistThread_.store(true);
99         SetNameInternal();
100     } else {
101         AutoLock lock(mutex_);
102         if (state_ != nullptr) {
103             state_.reset();
104         }
105         MEDIA_LOG_E("thread create failed, name: " PUBLIC_LOG_S ", rtv: " PUBLIC_LOG_D32, name_.c_str(), rtv);
106     }
107     return rtv == 0;
108 }
109 
IsRunningInSelf()110 bool Thread::IsRunningInSelf()
111 {
112     pthread_t tid = pthread_self();
113     AutoLock lock(mutex_);
114     return tid == id_;
115 }
116 
SetNameInternal()117 void Thread::SetNameInternal()
118 {
119     AutoLock lock(mutex_);
120     if (state_ && !name_.empty()) {
121         constexpr int threadNameMaxSize = 15;
122         if (name_.size() > threadNameMaxSize) {
123             MEDIA_LOG_W("task name " PUBLIC_LOG_S " exceed max size: " PUBLIC_LOG_D32,
124                         name_.c_str(), threadNameMaxSize);
125             name_ = name_.substr(0, threadNameMaxSize);
126         }
127         pthread_setname_np(id_, name_.c_str());
128     }
129 }
130 
UpdateThreadPriority(const uint32_t newPriority,const std::string & strBundleName)131 void Thread::UpdateThreadPriority(const uint32_t newPriority, const std::string &strBundleName)
132 {
133     MEDIA_LOG_I("winddraw update priority %{public}u %{public}s", newPriority, std::to_string(gettid()).c_str());
134     std::unordered_map<std::string, std::string> mapPayload;
135     mapPayload["bundleName"] = strBundleName;
136     mapPayload["pid"] = std::to_string(getpid());
137     mapPayload[std::to_string(gettid())] = std::to_string(newPriority);
138     OHOS::ResourceSchedule::ResSchedClient::GetInstance().ReportData(RES_TYPE, RES_VALUE, mapPayload);
139 }
140 
141 
Run(void * arg)142 void* Thread::Run(void* arg) // NOLINT: void*
143 {
144     std::function<void()> func;
145     std::string name;
146     {
147         auto currentThread = static_cast<Thread *>(arg);
148         AutoLock lock(currentThread->mutex_);
149         auto state = currentThread->state_.get();
150         if (state == nullptr) {
151             return nullptr;
152         }
153         func = state->func;
154         name = state->name;
155     }
156     func();
157     {
158         auto currentThread = static_cast<Thread *>(arg);
159         AutoLock lock(currentThread->mutex_);
160         currentThread->state_ = nullptr;
161     }
162     MEDIA_LOG_W("Thread " PUBLIC_LOG_S " exited...", name.c_str());
163     return nullptr;
164 }
165 } // namespace Media
166 } // namespace OHOS
167