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_strategy.h"
26 #ifdef FFRT_WORKERS_DYNAMIC_SCALING
27 #include "eu/blockaware.h"
28 #endif
29 #include "sync/sync.h"
30 
31 namespace ffrt {
32 struct WorkerCtrl {
33     alignas(cacheline_size) fast_mutex lock;
34     alignas(cacheline_size) int executionNum = 0;
35     alignas(cacheline_size) int sleepingWorkerNum = 0;
36     alignas(cacheline_size) bool irqEnable = false;
37     size_t hardLimit = 0;
38     size_t maxConcurrency = 0;
39     bool pollWaitFlag = false;
40     int deepSleepingWorkerNum = 0;
41     bool retryBeforeDeepSleep = true;
42 };
43 
44 class CPUMonitor {
45 public:
46     CPUMonitor(CpuMonitorOps&& ops);
47     CPUMonitor(const CPUMonitor&) = delete;
48     CPUMonitor& operator=(const CPUMonitor&) = delete;
49     virtual ~CPUMonitor();
50     uint32_t GetMonitorTid() const;
51     int TotalCount(const QoS& qos);
52     virtual void IntoSleep(const QoS& qos) = 0;
53     virtual void IntoPollWait(const QoS& qos) = 0;
54 
55     void WakeupSleep(const QoS& qos, bool irqWake = false);
56     void IntoDeepSleep(const QoS& qos);
57     void WakeupDeepSleep(const QoS& qos, bool irqWake = false);
58     void TimeoutCount(const QoS& qos);
59     bool IsExceedDeepSleepThreshold();
60     void OutOfPollWait(const QoS& qos);
61     void RollbackDestroy(const QoS& qos, bool irqWake = false);
62     bool TryDestroy(const QoS& qos);
63 #ifdef FFRT_WORKERS_DYNAMIC_SCALING
64     bool IsExceedRunningThreshold(const QoS& qos);
65     bool IsBlockAwareInit(void);
66     void MonitorMain();
67     BlockawareWakeupCond* WakeupCond(void);
68 #endif
69     virtual void Notify(const QoS& qos, TaskNotifyType notifyType) = 0;
70     virtual void WorkerInit() = 0;
71     int SetWorkerMaxNum(const QoS& qos, int num);
72     /* strategy options for handling task notify events */
73     static void HandleTaskNotifyDefault(const QoS& qos, void* p, TaskNotifyType notifyType);
74     static void HandleTaskNotifyConservative(const QoS& qos, void* p, TaskNotifyType notifyType);
75     static void HandleTaskNotifyUltraConservative(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     void StartMonitor();
80 
81     CpuMonitorOps ops;
82     std::thread* monitorThread = nullptr;
83     uint32_t monitorTid = 0;
84 protected:
85     WorkerCtrl ctrlQueue[QoS::MaxNum()];
86     void Poke(const QoS& qos, uint32_t taskCount, TaskNotifyType notifyType);
GetOps()87     CpuMonitorOps& GetOps()
88     {
89         return ops;
90     }
91 #ifdef FFRT_WORKERS_DYNAMIC_SCALING
92     bool blockAwareInit = false;
93     bool stopMonitor = false;
94     unsigned long keyPtr = 0;
95     int qosMonitorMaxNum = std::min(QoS::Max(), BLOCKAWARE_DOMAIN_ID_MAX + 1);
96     BlockawareWakeupCond wakeupCond;
97     BlockawareDomainInfoArea domainInfoMonitor;
98 #endif
99 private:
100     void SetupMonitor();
101     std::atomic<bool> setWorkerMaxNum[QoS::MaxNum()];
102 };
103 }
104 #endif /* CPU_MONITOR_H */