1 /*
2 * Copyright (c) 2024 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 "ark_idle_monitor.h"
17
18
19 #include "utils/log.h"
20 #if defined(ENABLE_FFRT)
21 #include "ffrt.h"
22 #include "c/executor_task.h"
23 #endif
24 #ifdef ENABLE_UCOLLECTION
25 #include "cpu_collector_client.h"
26 #endif
27 #ifdef ENABLE_HITRACE
28 #include "hitrace/trace.h"
29 #include "hitrace_meter.h"
30 #include "parameter.h"
31 #include "musl_preinit_common.h"
32 #include "memory_trace.h"
33 #endif
34 #include "ark_native_engine.h"
35
36 namespace panda::ecmascript {
37
NotifyLooperIdleStart(int64_t timestamp,int idleTime)38 void ArkIdleMonitor::NotifyLooperIdleStart(int64_t timestamp, [[maybe_unused]] int idleTime)
39 {
40 SetIdleState(true);
41 AddIdleNotifyCount();
42 recordedRunningNotifyInterval_.Push(timestamp - idleEndTimestamp_);
43 #ifndef DISABLE_SHORT_IDLE_CHECK
44 CheckShortIdleTask(timestamp, idleTime);
45 #endif
46 SetNotifyTimestamp(timestamp);
47 }
48
CheckShortIdleTask(int64_t timestamp,int idleTime)49 void ArkIdleMonitor::CheckShortIdleTask(int64_t timestamp, int idleTime)
50 {
51 #if defined(ENABLE_FFRT)
52 while (handlerWaitToStopCount_ > 0) {
53 if (timerHandlerQueue_.size() <= 0) {
54 handlerWaitToStopCount_ = 0;
55 break;
56 }
57 int handler = timerHandlerQueue_.front();
58 timerHandlerQueue_.pop();
59 int ret = ffrt_timer_stop(ffrt_qos_user_initiated, handler);
60 if (ret != 0) {
61 HILOG_ERROR("ArkIdleMonitor: ffrt_timer_stop error handler: timerHandler='%{public}d', ret='%{public}d'",
62 handler, ret);
63 }
64 handlerWaitToStopCount_--;
65 }
66 #endif
67 if (triggeredGC_ && mainVM_ != nullptr) {
68 #ifdef ENABLE_HITRACE
69 StartTrace(HITRACE_TAG_ACE, "NotifyLooperIdleStart::TriggeredGC");
70 #endif
71 triggeredGC_ = JSNApi::NotifyLooperIdleStart(mainVM_, timestamp, idleTime);
72 #ifdef ENABLE_HITRACE
73 FinishTrace(HITRACE_TAG_ACE);
74 #endif
75 return;
76 }
77 if (ShouldTryTriggerGC(timestamp - GetNotifyTimestamp()) &&
78 idleTime > MIN_TRIGGER_GC_IDLE_INTERVAL &&
79 needCheckIntervalIdle_) {
80 PostIdleCheckTask();
81 }
82 if (!needCheckIntervalIdle_) {
83 needCheckIntervalIdle_ = true;
84 }
85 }
86
ShouldTryTriggerGC(int64_t interval)87 bool ArkIdleMonitor::ShouldTryTriggerGC(int64_t interval)
88 {
89 if (interval < MIN_TRIGGER_GC_IDLE_INTERVAL ||
90 recordedIdleNotifyInterval_.Count() != IDLE_CHECK_INTERVAL_LENGTH) {
91 return false;
92 }
93 int64_t sumIdleInterval = recordedIdleNotifyInterval_.Sum([](int64_t a, int64_t b) {return a + b;}, 0);
94 int64_t averageIdleInterval = sumIdleInterval / recordedIdleNotifyInterval_.Count();
95 int64_t sumRunningInterval = recordedRunningNotifyInterval_.Sum([](int64_t a, int64_t b) {return a + b;}, 0);
96 int64_t averageRunningInterval = sumRunningInterval / recordedRunningNotifyInterval_.Count();
97 if (averageIdleInterval > MIN_TRIGGER_GC_IDLE_INTERVAL &&
98 averageRunningInterval <= MAX_TRIGGER_GC_RUNNING_INTERVAL) {
99 return true;
100 }
101 return false;
102 }
103
NotifyLooperIdleEnd(int64_t timestamp)104 void ArkIdleMonitor::NotifyLooperIdleEnd(int64_t timestamp)
105 {
106 idleEndTimestamp_ = timestamp;
107 SetIdleState(false);
108 int64_t duration = timestamp - GetNotifyTimestamp();
109 recordedIdleNotifyInterval_.Push(duration);
110 AddIdleDuration(duration);
111 if (mainVM_ != nullptr) {
112 JSNApi::NotifyLooperIdleEnd(mainVM_, timestamp);
113 }
114 }
115
CheckLowNotifyState() const116 bool ArkIdleMonitor::CheckLowNotifyState() const
117 {
118 uint32_t checkCounts = IsInBackground() ? IDLE_INBACKGROUND_CHECK_LENGTH : IDLE_CHECK_LENGTH;
119 HILOG_DEBUG("ArkIdleMonitor: low Notify checkCounts '%{public}d', result '%{public}d' ",
120 checkCounts, static_cast<int>(numberOfLowIdleNotifyCycles_));
121 return numberOfLowIdleNotifyCycles_ >= checkCounts;
122 }
123
CheckLowRunningDurationState() const124 bool ArkIdleMonitor::CheckLowRunningDurationState() const
125 {
126 uint32_t checkCounts = IsInBackground() ? IDLE_INBACKGROUND_CHECK_LENGTH : IDLE_CHECK_LENGTH;
127 HILOG_DEBUG("ArkIdleMonitor: low Duration checkCounts '%{public}d', result '%{public}d' ",
128 checkCounts, static_cast<int>(numberOfHighIdleTimeRatio_));
129 return numberOfHighIdleTimeRatio_ >= checkCounts;
130 }
131
IntervalMonitor()132 void ArkIdleMonitor::IntervalMonitor()
133 {
134 if (!timerMutex_.try_lock()) {
135 HILOG_INFO("ArkIdleMonitor: IntervalMonitor stop by timerMutex_");
136 return;
137 }
138 auto nowTimestamp = std::chrono::time_point_cast<std::chrono::milliseconds>(
139 std::chrono::high_resolution_clock::now()).time_since_epoch().count();
140 int64_t idleDuration = GetTotalIdleDuration() - lastTotalIdleDuration_;
141 if (IsIdleState()) {
142 idleDuration += (nowTimestamp - GetNotifyTimestamp());
143 }
144 lastTotalIdleDuration_ = GetTotalIdleDuration();
145 if (GetIdleNotifyCount() <= LOW_IDLE_NOTIFY_THRESHOLD) {
146 numberOfLowIdleNotifyCycles_++;
147 } else {
148 numberOfLowIdleNotifyCycles_ = 0U;
149 }
150 ResetIdleNotifyCount();
151 int64_t recordTotalDuration = nowTimestamp - startRecordTimestamp_;
152 if (recordTotalDuration <= 0) {
153 numberOfHighIdleTimeRatio_ = 0U;
154 HILOG_ERROR("ArkIdleMonitor: recordTotalDuration <= 0");
155 } else {
156 double idleTimeRatio = static_cast<double>(idleDuration) / recordTotalDuration;
157 HILOG_DEBUG("ArkIdleMonitor: idleTimeRatio '%{public}.2f'", idleTimeRatio);
158 idleTimeRatio >= IDLE_RATIO ? numberOfHighIdleTimeRatio_++ : (numberOfHighIdleTimeRatio_ = 0U);
159 }
160 startRecordTimestamp_ = nowTimestamp;
161 CheckWorkerEnvQueue();
162 uint32_t checkCounts = IsInBackground() ? IDLE_INBACKGROUND_CHECK_LENGTH : IDLE_CHECK_LENGTH;
163 uint32_t workThreadCheckCounts = checkCounts - IDLE_WORKER_TRIGGER_COUNT;
164 if (numberOfLowIdleNotifyCycles_ >= checkCounts &&
165 numberOfHighIdleTimeRatio_ >= checkCounts) {
166 NotifyMainThreadTryCompressGC();
167 PostMonitorTask(SLEEP_MONITORING_INTERVAL);
168 ClearIdleStats();
169 } else if (numberOfLowIdleNotifyCycles_ >= workThreadCheckCounts &&
170 numberOfHighIdleTimeRatio_ >= workThreadCheckCounts) {
171 NotifyOneWorkerThreadTryCompressGC();
172 PostMonitorTask(IDLE_MONITORING_INTERVAL);
173 } else {
174 PostMonitorTask(IDLE_MONITORING_INTERVAL);
175 }
176 timerMutex_.unlock();
177 }
178
PostMonitorTask(uint64_t delayMs)179 void ArkIdleMonitor::PostMonitorTask(uint64_t delayMs)
180 {
181 #if defined(ENABLE_FFRT)
182 auto task = [](void* idleMonitorPtr) {
183 if (idleMonitorPtr != nullptr) {
184 ArkIdleMonitor* arkIdleMonitor = reinterpret_cast<ArkIdleMonitor *>(idleMonitorPtr);
185 arkIdleMonitor->IntervalMonitor();
186 }
187 };
188 if (waitForStopTimerHandler_ != -1) {
189 int ret = ffrt_timer_stop(ffrt_qos_user_initiated, waitForStopTimerHandler_);
190 if (ret != 0) {
191 HILOG_ERROR("ArkIdleMonitor: ffrt_timer_stop error handler: timerHandler='%{public}d', ret='%{public}d'",
192 waitForStopTimerHandler_, ret);
193 }
194 }
195 waitForStopTimerHandler_ = currentTimerHandler_;
196 currentTimerHandler_ = ffrt_timer_start(ffrt_qos_user_initiated, delayMs, this, task, false);
197 #endif
198 }
199
~ArkIdleMonitor()200 ArkIdleMonitor::~ArkIdleMonitor()
201 {
202 #if defined(ENABLE_FFRT)
203 StopIdleMonitorTimerTask();
204 while (timerHandlerQueue_.size() > 0) {
205 ffrt_timer_stop(ffrt_qos_user_initiated, timerHandlerQueue_.front());
206 timerHandlerQueue_.pop();
207 }
208 #endif
209 }
210
ClearIdleStats()211 void ArkIdleMonitor::ClearIdleStats()
212 {
213 ResetIdleNotifyCount();
214 numberOfLowIdleNotifyCycles_ = 0U;
215 numberOfHighIdleTimeRatio_ = 0U;
216 }
217
NotifyMainThreadTryCompressGC()218 void ArkIdleMonitor::NotifyMainThreadTryCompressGC()
219 {
220 #if defined(ENABLE_EVENT_HANDLER)
221 double cpuUsage = GetCpuUsage();
222 if (cpuUsage >= IDLE_CPU_USAGE) {
223 HILOG_INFO("ArkIdleMonitor: Sending a quiet notification is canceled due to high CPU usage: %{public}.2f",
224 cpuUsage);
225 return;
226 }
227 if (mainThreadHandler_ == nullptr) {
228 mainThreadHandler_ = std::make_shared<OHOS::AppExecFwk::EventHandler>(
229 OHOS::AppExecFwk::EventRunner::GetMainEventRunner());
230 };
231 if (mainVM_ == nullptr) {
232 return;
233 }
234 auto task = [this]() {
235 JSNApi::TriggerIdleGC(mainVM_, TRIGGER_IDLE_GC_TYPE::FULL_GC);
236 if (CheckWorkerEnvQueueAllInIdle()) {
237 JSNApi::TriggerIdleGC(mainVM_, TRIGGER_IDLE_GC_TYPE::SHARED_FULL_GC);
238 }
239 };
240 mainThreadHandler_->PostTask(task, "ARKTS_IDLE_COMPRESS", 0, OHOS::AppExecFwk::EventQueue::Priority::IMMEDIATE);
241 #endif
242 }
243
NotifyMainThreadTryCompressGCByBackground()244 void ArkIdleMonitor::NotifyMainThreadTryCompressGCByBackground()
245 {
246 #if defined(ENABLE_EVENT_HANDLER)
247 if (mainVM_ == nullptr) {
248 return;
249 }
250 if (mainThreadHandler_ == nullptr) {
251 mainThreadHandler_ = std::make_shared<OHOS::AppExecFwk::EventHandler>(
252 OHOS::AppExecFwk::EventRunner::GetMainEventRunner());
253 };
254 auto task = [this]() {
255 JSNApi::TriggerIdleGC(mainVM_, TRIGGER_IDLE_GC_TYPE::FULL_GC);
256 JSNApi::TriggerIdleGC(mainVM_, TRIGGER_IDLE_GC_TYPE::SHARED_FULL_GC);
257 };
258 if (IsIdleState()) {
259 mainThreadHandler_->PostTask(task, "ARKTS_BACKGROUND_COMPRESS", 0,
260 OHOS::AppExecFwk::EventQueue::Priority::IMMEDIATE);
261 }
262 #endif
263 }
264
SetStartTimerCallback()265 void ArkIdleMonitor::SetStartTimerCallback()
266 {
267 JSNApi::SetStartIdleMonitorCallback([this]() {
268 this->IntervalMonitor();
269 started_ = true;
270 });
271 }
272
NotifyChangeBackgroundState(bool inBackground)273 void ArkIdleMonitor::NotifyChangeBackgroundState(bool inBackground)
274 {
275 inBackground_.store(inBackground, std::memory_order_relaxed);
276 ClearIdleStats();
277 if (!started_ && inBackground) {
278 HILOG_DEBUG("ArkIdleMonitor change to background but not started idle check");
279 return;
280 }
281 #if defined(ENABLE_FFRT)
282 if (started_ && inBackground) {
283 HILOG_DEBUG("ArkIdleMonitor post check switch background gc task");
284 StopIdleMonitorTimerTask();
285 PostSwitchBackgroundGCTask();
286 }
287 #endif
288 }
289
GetCpuUsage() const290 double ArkIdleMonitor::GetCpuUsage() const
291 {
292 #ifdef ENABLE_UCOLLECTION
293 auto collector = OHOS::HiviewDFX::UCollectClient::CpuCollector::Create();
294 auto collectResult = collector->GetSysCpuUsage();
295 if (collectResult.retCode == OHOS::HiviewDFX::UCollect::UcError::SUCCESS) {
296 HILOG_DEBUG("ArkIdleMonitor cpu usage: %{public}.2f", collectResult.data);
297 return collectResult.data;
298 }
299 HILOG_ERROR("ArkIdleMonitor get cpu usage failed, error code:%{public}d", collectResult.retCode);
300 #endif
301 return 0.0f;
302 }
303
CheckIntervalIdle(int64_t timestamp,int64_t idleDuration)304 bool ArkIdleMonitor::CheckIntervalIdle(int64_t timestamp, int64_t idleDuration)
305 {
306 if (!IsIdleState()) {
307 return false;
308 }
309 int64_t nowTimestamp = std::chrono::time_point_cast<std::chrono::milliseconds>(
310 std::chrono::high_resolution_clock::now()).time_since_epoch().count();
311 int64_t sumDuration = nowTimestamp - timestamp;
312 int64_t sumIdleDuration = (GetTotalIdleDuration() - idleDuration) + (nowTimestamp - GetNotifyTimestamp());
313 [[maybe_unused]] double idlePercentage = static_cast<double>(sumIdleDuration) / static_cast<double>(sumDuration);
314 #ifdef ENABLE_HITRACE
315 StartTrace(HITRACE_TAG_ACE, "CheckIntervalIdle::sumDuration:" + std::to_string(sumDuration)
316 + "sumIdleDuration:" + std::to_string(sumIdleDuration)
317 + "idlePercentage" + std::to_string(idlePercentage));
318 #endif
319 #if defined(ENABLE_EVENT_HANDLER)
320 if (idlePercentage > SHORT_IDLE_RATIO && mainVM_!= nullptr) {
321 if (mainThreadHandler_ == nullptr) {
322 mainThreadHandler_ = std::make_shared<OHOS::AppExecFwk::EventHandler>(
323 OHOS::AppExecFwk::EventRunner::GetMainEventRunner());
324 };
325 auto task = [this]() {
326 triggeredGC_ = JSNApi::NotifyLooperIdleStart(mainVM_, 0, 0);
327 needCheckIntervalIdle_ = false;
328 handlerWaitToStopCount_++;
329 // If GC is triggered, reset the statistics to avoid triggering monitoring tasks continuously.
330 if (!triggeredGC_) {
331 recordedIdleNotifyInterval_.Reset();
332 }
333 };
334 mainThreadHandler_->PostTask(task, "ARKTS_IDLE_NOTIFY", 0, OHOS::AppExecFwk::EventQueue::Priority::IMMEDIATE);
335 }
336 #endif
337 #ifdef ENABLE_HITRACE
338 FinishTrace(HITRACE_TAG_ACE);
339 #endif
340 return true;
341 }
342
PostIdleCheckTask()343 void ArkIdleMonitor::PostIdleCheckTask()
344 {
345 #ifdef ENABLE_HITRACE
346 StartTrace(HITRACE_TAG_ACE, "NotifyLooperIdleStart::PostIdleCheckTask");
347 #endif
348 #if defined(ENABLE_FFRT)
349 auto nowTimestamp = std::chrono::time_point_cast<std::chrono::milliseconds>(
350 std::chrono::high_resolution_clock::now()).time_since_epoch().count();
351 std::tuple<ArkIdleMonitor*, int64_t, int64_t> myTuple = std::make_tuple(this, nowTimestamp, GetTotalIdleDuration());
352 std::tuple<ArkIdleMonitor*, int64_t, int64_t> *data = new std::tuple<ArkIdleMonitor*, int64_t, int64_t>(myTuple);
353 auto task = [](void* data) {
354 std::tuple<ArkIdleMonitor*, int64_t, int64_t>* tuple =
355 reinterpret_cast<std::tuple<ArkIdleMonitor*, int64_t, int64_t>*>(data);
356 if (tuple == nullptr || std::get<0>(*tuple) == nullptr) {
357 return;
358 }
359 std::get<0>(*tuple)->CheckIntervalIdle(std::get<1>(*tuple), std::get<2>(*tuple));
360 delete tuple;
361 };
362 int timerHandler = ffrt_timer_start(ffrt_qos_user_initiated, SHORT_IDLE_DELAY_INTERVAL,
363 reinterpret_cast<void*>(data), task, false);
364 timerHandlerQueue_.push(timerHandler);
365 #endif
366 #ifdef ENABLE_HITRACE
367 FinishTrace(HITRACE_TAG_ACE);
368 #endif
369 }
370
SwitchBackgroundCheckGCTask(int64_t timestamp,int64_t idleDuration)371 void ArkIdleMonitor::SwitchBackgroundCheckGCTask(int64_t timestamp, int64_t idleDuration)
372 {
373 int64_t nowTimestamp = std::chrono::time_point_cast<std::chrono::milliseconds>(
374 std::chrono::high_resolution_clock::now()).time_since_epoch().count();
375 int64_t sumDuration = nowTimestamp - timestamp;
376 int64_t sumIdleDuration = (GetTotalIdleDuration() - idleDuration) + (nowTimestamp - GetNotifyTimestamp());
377 double idlePercentage = static_cast<double>(sumIdleDuration) / static_cast<double>(sumDuration);
378 double cpuUsage = GetCpuUsage();
379 if (idlePercentage > BACKGROUND_IDLE_RATIO && cpuUsage <= IDLE_BACKGROUND_CPU_USAGE) {
380 NotifyMainThreadTryCompressGCByBackground();
381 } else {
382 HILOG_INFO("ArkIdleMonitor canceled background GC task, idlePercentage:%{public}.2f, cpuUsage:%{public}.2f",
383 idlePercentage, cpuUsage);
384 }
385 PostMonitorTask(SLEEP_MONITORING_INTERVAL);
386 ClearIdleStats();
387 }
388
PostSwitchBackgroundGCTask()389 void ArkIdleMonitor::PostSwitchBackgroundGCTask()
390 {
391 #if defined(ENABLE_FFRT)
392 if (switchBackgroundTimerHandler_ != -1) {
393 ffrt_timer_stop(ffrt_qos_user_initiated, switchBackgroundTimerHandler_);
394 }
395 auto nowTimestamp = std::chrono::time_point_cast<std::chrono::milliseconds>(
396 std::chrono::high_resolution_clock::now()).time_since_epoch().count();
397 std::tuple<ArkIdleMonitor*, int64_t, int64_t> myTuple = std::make_tuple(this, nowTimestamp, GetTotalIdleDuration());
398 std::tuple<ArkIdleMonitor*, int64_t, int64_t> *data = new std::tuple<ArkIdleMonitor*, int64_t, int64_t>(myTuple);
399 auto task = [](void* data) {
400 std::tuple<ArkIdleMonitor*, int64_t, int64_t>* tuple =
401 reinterpret_cast<std::tuple<ArkIdleMonitor*, int64_t, int64_t>*>(data);
402 if (tuple == nullptr || std::get<0>(*tuple) == nullptr) {
403 return;
404 }
405 std::get<0>(*tuple)->SwitchBackgroundCheckGCTask(std::get<1>(*tuple), std::get<2>(*tuple));
406 delete tuple;
407 };
408 switchBackgroundTimerHandler_ = ffrt_timer_start(ffrt_qos_user_initiated, IDLE_MONITORING_INTERVAL,
409 reinterpret_cast<void*>(data), task, false);
410 #endif
411 }
412
CheckWorkerEnvQueue()413 void ArkIdleMonitor::CheckWorkerEnvQueue()
414 {
415 std::lock_guard<std::mutex> lock(queueMutex_);
416 for (size_t i = 0; i < workerEnvQueue_.size(); i++) {
417 napi_env env = workerEnvQueue_.front();
418 auto arkNativeEngine = reinterpret_cast<ArkNativeEngine*>(env);
419 workerEnvQueue_.pop();
420 workerEnvQueue_.push(env);
421 arkNativeEngine->GetWorkerThreadState()->CheckIdleState();
422 HILOG_DEBUG("ArkIdleMonitor::CheckWorkerEnvQueue,tid=%{public}d, workerCount=%{public}d",
423 arkNativeEngine->GetSysTid(), arkNativeEngine->GetWorkerThreadState()->GetCheckCount());
424 }
425 }
426
CheckWorkerEnvQueueAllInIdle()427 bool ArkIdleMonitor::CheckWorkerEnvQueueAllInIdle()
428 {
429 std::lock_guard<std::mutex> lock(queueMutex_);
430 for (size_t i = 0; i < workerEnvQueue_.size(); i++) {
431 napi_env env = workerEnvQueue_.front();
432 auto arkNativeEngine = reinterpret_cast<ArkNativeEngine*>(env);
433 if (arkNativeEngine->GetWorkerThreadState()->GetCheckCount() < IDLE_INBACKGROUND_CHECK_LENGTH) {
434 return false;
435 }
436 workerEnvQueue_.pop();
437 workerEnvQueue_.push(env);
438 }
439 return true;
440 }
441
NotifyOneWorkerThreadTryCompressGC()442 void ArkIdleMonitor::NotifyOneWorkerThreadTryCompressGC()
443 {
444 std::lock_guard<std::mutex> lock(queueMutex_);
445 for (size_t i = 0; i < workerEnvQueue_.size(); i++) {
446 napi_env env = workerEnvQueue_.front();
447 workerEnvQueue_.pop();
448 workerEnvQueue_.push(env);
449 auto arkNativeEngine = reinterpret_cast<ArkNativeEngine*>(env);
450 if (arkNativeEngine->GetWorkerThreadState()->GetCheckCount() >= IDLE_INBACKGROUND_CHECK_LENGTH) {
451 std::pair<void*, uint8_t> data(reinterpret_cast<void*>(const_cast<EcmaVM*>(arkNativeEngine->GetEcmaVm())),
452 static_cast<uint8_t>(TRIGGER_IDLE_GC_TYPE::FULL_GC));
453 arkNativeEngine->PostTriggerGCTask(data);
454 return;
455 }
456 }
457 }
458
StopIdleMonitorTimerTask()459 void ArkIdleMonitor::StopIdleMonitorTimerTask()
460 {
461 #if defined(ENABLE_FFRT)
462 std::lock_guard<std::mutex> lock(timerMutex_);
463 HILOG_INFO("StopIdleMonitorTimerTask get timerMutex_");
464 if (currentTimerHandler_ != -1) {
465 ffrt_timer_stop(ffrt_qos_user_initiated, currentTimerHandler_);
466 currentTimerHandler_ = -1;
467 }
468 if (waitForStopTimerHandler_ != -1) {
469 ffrt_timer_stop(ffrt_qos_user_initiated, waitForStopTimerHandler_);
470 waitForStopTimerHandler_ = -1;
471 }
472 #endif
473 }
474
475
476 std::shared_ptr<ArkIdleMonitor> ArkIdleMonitor::instance_ = std::make_shared<ArkIdleMonitor>();
477
GetInstance()478 std::shared_ptr<ArkIdleMonitor> ArkIdleMonitor::GetInstance()
479 {
480 return instance_;
481 }
482 }
483
484