1484543d1Sopenharmony_ci/* 2484543d1Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 3484543d1Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4484543d1Sopenharmony_ci * you may not use this file except in compliance with the License. 5484543d1Sopenharmony_ci * You may obtain a copy of the License at 6484543d1Sopenharmony_ci * 7484543d1Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8484543d1Sopenharmony_ci * 9484543d1Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10484543d1Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11484543d1Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12484543d1Sopenharmony_ci * See the License for the specific language governing permissions and 13484543d1Sopenharmony_ci * limitations under the License. 14484543d1Sopenharmony_ci */ 15484543d1Sopenharmony_ci 16484543d1Sopenharmony_ci#ifndef FFRT_WORKER_THREAD_HPP 17484543d1Sopenharmony_ci#define FFRT_WORKER_THREAD_HPP 18484543d1Sopenharmony_ci 19484543d1Sopenharmony_ci#include <atomic> 20484543d1Sopenharmony_ci#include <unistd.h> 21484543d1Sopenharmony_ci#ifdef FFRT_PTHREAD_ENABLE 22484543d1Sopenharmony_ci#include <pthread.h> 23484543d1Sopenharmony_ci#endif 24484543d1Sopenharmony_ci#include <thread> 25484543d1Sopenharmony_ci#ifdef OHOS_THREAD_STACK_DUMP 26484543d1Sopenharmony_ci#include <sstream> 27484543d1Sopenharmony_ci#include "dfx_dump_catcher.h" 28484543d1Sopenharmony_ci#endif 29484543d1Sopenharmony_ci 30484543d1Sopenharmony_ci#include "qos.h" 31484543d1Sopenharmony_ci#include "tm/cpu_task.h" 32484543d1Sopenharmony_ci#include "dfx/log/ffrt_log_api.h" 33484543d1Sopenharmony_ci 34484543d1Sopenharmony_cinamespace ffrt { 35484543d1Sopenharmony_ciconstexpr int PTHREAD_CREATE_NO_MEM_CODE = 11; 36484543d1Sopenharmony_ciconstexpr int FFRT_RETRY_MAX_COUNT = 12; 37484543d1Sopenharmony_ciconst std::vector<uint64_t> FFRT_RETRY_CYCLE_LIST = { 38484543d1Sopenharmony_ci 10 * 1000, 50 * 1000, 100 * 1000, 200 * 1000, 500 * 1000, 1000 * 1000, 2 * 1000 * 1000, 39484543d1Sopenharmony_ci 5 * 1000 * 1000, 10 * 1000 * 1000, 50 * 1000 * 1000, 100 * 1000 * 1000, 500 * 1000 * 1000 40484543d1Sopenharmony_ci}; 41484543d1Sopenharmony_ci 42484543d1Sopenharmony_ciclass WorkerThread { 43484543d1Sopenharmony_cipublic: 44484543d1Sopenharmony_ci CPUEUTask* curTask = nullptr; 45484543d1Sopenharmony_ci 46484543d1Sopenharmony_ci uintptr_t curTaskType_ = ffrt_invalid_task; 47484543d1Sopenharmony_ci std::string curTaskLabel_ = ""; 48484543d1Sopenharmony_ci uint64_t curTaskGid_ = UINT64_MAX; //仅当TaskType为normal task或者queue task时,label和gid才能正常读取 49484543d1Sopenharmony_ci explicit WorkerThread(const QoS& qos); 50484543d1Sopenharmony_ci 51484543d1Sopenharmony_ci virtual ~WorkerThread() 52484543d1Sopenharmony_ci { 53484543d1Sopenharmony_ci if (!exited) { 54484543d1Sopenharmony_ci#ifdef OHOS_THREAD_STACK_DUMP 55484543d1Sopenharmony_ci FFRT_LOGW("WorkerThread enter destruction but not exited"); 56484543d1Sopenharmony_ci OHOS::HiviewDFX::DfxDumpCatcher dumplog; 57484543d1Sopenharmony_ci std::string msg = ""; 58484543d1Sopenharmony_ci bool result = dumplog.DumpCatch(getpid(), gettid(), msg); 59484543d1Sopenharmony_ci if (result) { 60484543d1Sopenharmony_ci std::vector<std::string> out; 61484543d1Sopenharmony_ci std::stringstream ss(msg); 62484543d1Sopenharmony_ci std::string s; 63484543d1Sopenharmony_ci while (std::getline(ss, s, '\n')) { 64484543d1Sopenharmony_ci out.push_back(s); 65484543d1Sopenharmony_ci } 66484543d1Sopenharmony_ci for (auto const& line: out) { 67484543d1Sopenharmony_ci FFRT_LOGE("ffrt callstack %s", line.c_str()); 68484543d1Sopenharmony_ci } 69484543d1Sopenharmony_ci } 70484543d1Sopenharmony_ci#endif 71484543d1Sopenharmony_ci } 72484543d1Sopenharmony_ci FFRT_LOGW("WorkerThread enter destruction"); 73484543d1Sopenharmony_ci Detach(); 74484543d1Sopenharmony_ci } 75484543d1Sopenharmony_ci 76484543d1Sopenharmony_ci bool Idle() const 77484543d1Sopenharmony_ci { 78484543d1Sopenharmony_ci return idle; 79484543d1Sopenharmony_ci } 80484543d1Sopenharmony_ci 81484543d1Sopenharmony_ci void SetIdle(bool var) 82484543d1Sopenharmony_ci { 83484543d1Sopenharmony_ci this->idle = var; 84484543d1Sopenharmony_ci } 85484543d1Sopenharmony_ci 86484543d1Sopenharmony_ci bool Exited() const 87484543d1Sopenharmony_ci { 88484543d1Sopenharmony_ci return exited; 89484543d1Sopenharmony_ci } 90484543d1Sopenharmony_ci 91484543d1Sopenharmony_ci void SetExited(bool var) 92484543d1Sopenharmony_ci { 93484543d1Sopenharmony_ci this->exited = var; 94484543d1Sopenharmony_ci } 95484543d1Sopenharmony_ci 96484543d1Sopenharmony_ci pid_t Id() const 97484543d1Sopenharmony_ci { 98484543d1Sopenharmony_ci while (!exited && tid < 0) { 99484543d1Sopenharmony_ci } 100484543d1Sopenharmony_ci return tid; 101484543d1Sopenharmony_ci } 102484543d1Sopenharmony_ci 103484543d1Sopenharmony_ci const QoS& GetQos() const 104484543d1Sopenharmony_ci { 105484543d1Sopenharmony_ci return qos; 106484543d1Sopenharmony_ci } 107484543d1Sopenharmony_ci#ifdef FFRT_WORKERS_DYNAMIC_SCALING 108484543d1Sopenharmony_ci unsigned int GetDomainId() const 109484543d1Sopenharmony_ci { 110484543d1Sopenharmony_ci return domain_id; 111484543d1Sopenharmony_ci } 112484543d1Sopenharmony_ci#endif 113484543d1Sopenharmony_ci 114484543d1Sopenharmony_ci#ifdef FFRT_PTHREAD_ENABLE 115484543d1Sopenharmony_ci void Start(void*(*ThreadFunc)(void*), void* args) 116484543d1Sopenharmony_ci { 117484543d1Sopenharmony_ci int ret = pthread_create(&thread_, &attr_, ThreadFunc, args); 118484543d1Sopenharmony_ci if (ret == PTHREAD_CREATE_NO_MEM_CODE) { 119484543d1Sopenharmony_ci int count = 0; 120484543d1Sopenharmony_ci while (ret == PTHREAD_CREATE_NO_MEM_CODE && count < FFRT_RETRY_MAX_COUNT) { 121484543d1Sopenharmony_ci usleep(FFRT_RETRY_CYCLE_LIST[count]); 122484543d1Sopenharmony_ci count++; 123484543d1Sopenharmony_ci FFRT_LOGW("pthread_create failed due to shortage of system memory, FFRT retry %d times...", count); 124484543d1Sopenharmony_ci ret = pthread_create(&thread_, &attr_, ThreadFunc, args); 125484543d1Sopenharmony_ci } 126484543d1Sopenharmony_ci } 127484543d1Sopenharmony_ci if (ret != 0) { 128484543d1Sopenharmony_ci FFRT_LOGE("pthread_create failed, ret = %d", ret); 129484543d1Sopenharmony_ci exited = true; 130484543d1Sopenharmony_ci } 131484543d1Sopenharmony_ci pthread_attr_destroy(&attr_); 132484543d1Sopenharmony_ci } 133484543d1Sopenharmony_ci 134484543d1Sopenharmony_ci void Join() 135484543d1Sopenharmony_ci { 136484543d1Sopenharmony_ci if (tid > 0) { 137484543d1Sopenharmony_ci pthread_join(thread_, nullptr); 138484543d1Sopenharmony_ci } 139484543d1Sopenharmony_ci tid = -1; 140484543d1Sopenharmony_ci } 141484543d1Sopenharmony_ci 142484543d1Sopenharmony_ci void Detach() 143484543d1Sopenharmony_ci { 144484543d1Sopenharmony_ci if (tid > 0) { 145484543d1Sopenharmony_ci pthread_detach(thread_); 146484543d1Sopenharmony_ci } else { 147484543d1Sopenharmony_ci FFRT_LOGD("qos %d thread not joinable.", qos()); 148484543d1Sopenharmony_ci } 149484543d1Sopenharmony_ci tid = -1; 150484543d1Sopenharmony_ci } 151484543d1Sopenharmony_ci 152484543d1Sopenharmony_ci pthread_t& GetThread() 153484543d1Sopenharmony_ci { 154484543d1Sopenharmony_ci return this->thread_; 155484543d1Sopenharmony_ci } 156484543d1Sopenharmony_ci#else 157484543d1Sopenharmony_ci template <typename F, typename... Args> 158484543d1Sopenharmony_ci void Start(F&& f, Args&&... args) 159484543d1Sopenharmony_ci { 160484543d1Sopenharmony_ci auto wrap = [&](Args&&... args) { 161484543d1Sopenharmony_ci NativeConfig(); 162484543d1Sopenharmony_ci return f(args...); 163484543d1Sopenharmony_ci }; 164484543d1Sopenharmony_ci thread = std::thread(wrap, args...); 165484543d1Sopenharmony_ci } 166484543d1Sopenharmony_ci 167484543d1Sopenharmony_ci void Join() 168484543d1Sopenharmony_ci { 169484543d1Sopenharmony_ci if (thread.joinable()) { 170484543d1Sopenharmony_ci thread.join(); 171484543d1Sopenharmony_ci } 172484543d1Sopenharmony_ci tid = -1; 173484543d1Sopenharmony_ci } 174484543d1Sopenharmony_ci 175484543d1Sopenharmony_ci void Detach() 176484543d1Sopenharmony_ci { 177484543d1Sopenharmony_ci if (thread.joinable()) { 178484543d1Sopenharmony_ci thread.detach(); 179484543d1Sopenharmony_ci } else { 180484543d1Sopenharmony_ci FFRT_LOGD("qos %d thread not joinable\n", qos()); 181484543d1Sopenharmony_ci } 182484543d1Sopenharmony_ci tid = -1; 183484543d1Sopenharmony_ci } 184484543d1Sopenharmony_ci 185484543d1Sopenharmony_ci pthread_t GetThread() 186484543d1Sopenharmony_ci { 187484543d1Sopenharmony_ci return this->thread.native_handle(); 188484543d1Sopenharmony_ci } 189484543d1Sopenharmony_ci#endif 190484543d1Sopenharmony_ci 191484543d1Sopenharmony_ci void WorkerSetup(WorkerThread* wthread); 192484543d1Sopenharmony_ci void NativeConfig(); 193484543d1Sopenharmony_ci 194484543d1Sopenharmony_ciprivate: 195484543d1Sopenharmony_ci std::atomic_bool exited; 196484543d1Sopenharmony_ci std::atomic_bool idle; 197484543d1Sopenharmony_ci 198484543d1Sopenharmony_ci std::atomic<pid_t> tid; 199484543d1Sopenharmony_ci 200484543d1Sopenharmony_ci QoS qos; 201484543d1Sopenharmony_ci#ifdef FFRT_PTHREAD_ENABLE 202484543d1Sopenharmony_ci pthread_t thread_{0}; 203484543d1Sopenharmony_ci pthread_attr_t attr_; 204484543d1Sopenharmony_ci#else 205484543d1Sopenharmony_ci std::thread thread; 206484543d1Sopenharmony_ci#endif 207484543d1Sopenharmony_ci#ifdef FFRT_WORKERS_DYNAMIC_SCALING 208484543d1Sopenharmony_ci unsigned int domain_id; 209484543d1Sopenharmony_ci#endif 210484543d1Sopenharmony_ci}; 211484543d1Sopenharmony_civoid SetThreadAttr(WorkerThread* thread, const QoS& qos); 212484543d1Sopenharmony_ci} // namespace ffrt 213484543d1Sopenharmony_ci#endif 214