1 /*
2  * Copyright (c) 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 #include "eu/worker_thread.h"
17 #include <algorithm>
18 #include <unistd.h>
19 #include <sys/syscall.h>
20 #include "dfx/log/ffrt_log_api.h"
21 #ifdef FFRT_WORKERS_DYNAMIC_SCALING
22 #include "eu/blockaware.h"
23 #endif
24 #include "eu/execute_unit.h"
25 #include "eu/osattr_manager.h"
26 #include "eu/qos_interface.h"
27 #include "qos.h"
28 #include "util/ffrt_facade.h"
29 #include "util/name_manager.h"
30 
31 namespace ffrt {
WorkerThread(const QoS & qos)32 WorkerThread::WorkerThread(const QoS& qos) : exited(false), idle(false), tid(-1), qos(qos)
33 {
34 #ifdef FFRT_PTHREAD_ENABLE
35     pthread_attr_init(&attr_);
36     size_t stackSize = FFRTFacade::GetEUInstance().GetGroupCtl()[qos()].workerStackSize;
37     if (stackSize > 0) {
38         pthread_attr_setstacksize(&attr_, stackSize);
39     }
40 #endif
41 #ifdef FFRT_WORKERS_DYNAMIC_SCALING
42     domain_id = (qos() <= BLOCKAWARE_DOMAIN_ID_MAX) ? qos() : BLOCKAWARE_DOMAIN_ID_MAX + 1;
43 #endif
44 }
45 
NativeConfig()46 void WorkerThread::NativeConfig()
47 {
48     pid_t pid = syscall(SYS_gettid);
49     this->tid = pid;
50     SetThreadAttr(this, qos);
51 }
52 
WorkerSetup(WorkerThread * wthread)53 void WorkerThread::WorkerSetup(WorkerThread* wthread)
54 {
55     static int threadIndex[QoS::MaxNum()] = {0};
56     std::string qosStr = std::to_string(qos());
57     std::string threadName = std::string(WORKER_THREAD_NAME_PREFIX) + qosStr +
58         std::string(WORKER_THREAD_SYMBOL) + std::to_string(threadIndex[qos()]++);
59     if (qosStr == "") {
60         FFRT_LOGE("ffrt threadName qos[%d] index[%d]", qos(), threadIndex[qos()]);
61     }
62     pthread_setname_np(wthread->GetThread(), threadName.c_str());
63 }
64 
SetCpuAffinity(unsigned long affinity,int tid)65 int SetCpuAffinity(unsigned long affinity, int tid)
66 {
67     cpu_set_t mask;
68     CPU_ZERO(&mask);
69     for (unsigned long i = 0; i < sizeof(affinity) * 8; i++) {
70         if ((affinity & (static_cast<unsigned long>(1) << i)) != 0) {
71             CPU_SET(i, &mask);
72         }
73     }
74     int ret = syscall(__NR_sched_setaffinity, tid, sizeof(mask), &mask);
75     if (ret < 0) {
76         FFRT_LOGE("set qos affinity failed for tid %d\n", tid);
77     }
78     return ret;
79 }
80 
SetThreadAttr(WorkerThread * thread,const QoS & qos)81 void SetThreadAttr(WorkerThread* thread, const QoS& qos)
82 {
83     if (qos() <= qos_max) {
84         FFRTQosApplyForOther(qos(), thread->Id());
85         FFRT_LOGD("qos apply tid[%d] level[%d]\n", thread->Id(), qos());
86     }
87 }
88 }; // namespace ffrt
89