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 #ifndef CPU_MONITOR_H
17 #define CPU_MONITOR_H
18 
19 #include <atomic>
20 #include <vector>
21 #include <functional>
22 #include <mutex>
23 #include "qos.h"
24 #include "cpp/mutex.h"
25 #include "eu/cpu_manager_interface.h"
26 #include "c/type_def_ext.h"
27 #include "util/token.h"
28 #include "internal_inc/config.h"
29 #ifdef FFRT_WORKERS_DYNAMIC_SCALING
30 #include "eu/blockaware.h"
31 #endif
32 
33 namespace ffrt {
34 
35 struct WorkerCtrl {
36     size_t hardLimit = 0;
37     size_t maxConcurrency = 0;
38     size_t reserveNum = 0;
39     int executionNum = 0;
40     int sleepingWorkerNum = 0;
41     bool pollWaitFlag = false;
42     int deepSleepingWorkerNum = 0;
43     bool hasWorkDeepSleep = false;
44     bool retryBeforeDeepSleep = true;
45     std::mutex lock;
46 };
47 
48 class CPUMonitor {
49 public:
50     CPUMonitor(CpuMonitorOps&& ops);
51     CPUMonitor(const CPUMonitor&) = delete;
52     CPUMonitor& operator=(const CPUMonitor&) = delete;
53     virtual ~CPUMonitor();
54     uint32_t GetMonitorTid() const;
55     virtual SleepType IntoSleep(const QoS& qos) = 0;
56     virtual void WakeupCount(const QoS& qos, bool isDeepSleepWork = false);
57     void IntoDeepSleep(const QoS& qos);
58     void OutOfDeepSleep(const QoS& qos);
59     void TimeoutCount(const QoS& qos);
60     bool IsExceedDeepSleepThreshold();
61     void IntoPollWait(const QoS& qos);
62     void OutOfPollWait(const QoS& qos);
63     void DoDestroy(const QoS& qos);
64 #ifdef FFRT_WORKERS_DYNAMIC_SCALING
65     bool IsExceedRunningThreshold(const QoS& qos);
66     bool IsBlockAwareInit(void);
67     void MonitorMain();
68     BlockawareWakeupCond* WakeupCond(void);
69 #endif
70     virtual void Notify(const QoS& qos, TaskNotifyType notifyType) = 0;
71     virtual void WorkerInit() = 0;
72     int QosWorkerNumSegment (ffrt_worker_num_param* qosData);
73     bool TryAcquirePublicWorkerNum(const QoS& qos);
74     /* strategy options for handling task notify events */
75     static void HandleTaskNotifyDefault(const QoS& qos, void* p, TaskNotifyType notifyType);
76     int WakedWorkerNum(const QoS& qos);
77     int SleepingWorkerNum(const QoS& qos);
78     void NotifyWorkers(const QoS& qos, int number);
79     bool HasDeepSleepWork(const QoS& qos);
80     uint32_t monitorTid = 0;
81 protected:
82     WorkerCtrl ctrlQueue[QoS::MaxNum()];
83     void PokeAdd(const QoS& qos);
84     void PokePick(const QoS& qos);
85     void Poke(const QoS& qos, uint32_t taskCount, TaskNotifyType notifyType);
GetOps()86     CpuMonitorOps& GetOps()
87     {
88         return ops;
89     }
90 private:
91     void SetupMonitor();
92     void StartMonitor();
93 
94     std::thread* monitorThread;
95     CpuMonitorOps ops;
96     bool setWorkerNum = false;
97     std::mutex setWorkerNumLock;
98     void SetWorkerPara(unsigned int& param, unsigned int value);
99     int SetQosWorkerPara(ffrt_qos_config& qosCfg);
100     bool QosWorkerNumValid(ffrt_worker_num_param* qosData);
101     bool LowQosUseReserveWorkerNum();
102     bool HighQosUseReserveWorkerNum();
103     void ReleasePublicWorkerNum(const QoS& qos);
104     void LogAllWorkerNum();
105     unsigned int globalReserveWorkerNum = 0;
106     unsigned int lowQosReserveWorkerNum = 0;
107     unsigned int highQosReserveWorkerNum = 0;
108     std::unique_ptr<Token> globalReserveWorkerToken = nullptr;
109     std::unique_ptr<Token> lowQosReserveWorkerToken = nullptr;
110     std::unique_ptr<Token> highQosReserveWorkerToken = nullptr;
111     std::unique_ptr<Token> lowQosUseGlobalWorkerToken = nullptr;
112     std::unique_ptr<Token> highQosUseGlobalWorkerToken = nullptr;
113     QosWorkerConfig qosWorkerConfig;
114 #ifdef FFRT_WORKERS_DYNAMIC_SCALING
115     bool blockAwareInit = false;
116     bool stopMonitor = false;
117     unsigned long keyPtr = 0;
118     int qosMonitorMaxNum = std::min(QoS::Max(), BLOCKAWARE_DOMAIN_ID_MAX + 1);
119     BlockawareWakeupCond wakeupCond;
120     BlockawareDomainInfoArea domainInfoMonitor;
121     BlockawareDomainInfoArea domainInfoNotify;
122     std::atomic<bool> exceedUpperWaterLine[QoS::MaxNum()];
123 #endif
124 };
125 }
126 #endif /* CPU_MONITOR_H */
127