• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "watchdog.h"
17 #include <mutex>
18 
19 namespace {
20     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "watchdog"};
21 }
22 
23 namespace OHOS {
24 namespace Media {
~WatchDog()25 WatchDog::~WatchDog()
26 {
27     DisableWatchDog();
28 }
29 
EnableWatchDog()30 void WatchDog::EnableWatchDog()
31 {
32     while (true) {
33         std::unique_lock<std::mutex> lock(mutex_);
34         if (enable_) {
35             return;
36         }
37 
38         if (disabling.load()) {
39             continue; // Wait for disable execution to finish.
40         }
41 
42         enable_ = true;
43         thread_ = std::make_unique<std::thread>(&WatchDog::WatchDogThread, this);
44         break;
45     }
46 };
47 
DisableWatchDog()48 void WatchDog::DisableWatchDog()
49 {
50     std::unique_lock<std::mutex> lock(mutex_);
51     if (disabling.load() == false) {
52         disabling.store(true);
53         enable_ = false;
54         cond_.notify_all();
55         lock.unlock(); // Make the thread acquire the lock and exit.
56         if (thread_ != nullptr && thread_->joinable()) {
57             thread_->join();
58             thread_.reset();
59             thread_ = nullptr;
60         }
61 
62         // It may be changed by thread. Assign value after thread recycle.
63         pause_ = false;
64         alarmed_ = false;
65         disabling.store(false);
66     }
67 };
68 
PauseWatchDog()69 void WatchDog::PauseWatchDog()
70 {
71     std::unique_lock<std::mutex> lock(mutex_);
72     if (enable_) {
73         pause_ = true;
74         paused_ = true;
75         cond_.notify_all();
76     }
77 };
78 
ResumeWatchDog()79 void WatchDog::ResumeWatchDog()
80 {
81     std::unique_lock<std::mutex> lock(mutex_);
82     if (enable_) {
83         pause_ = false;
84         cond_.notify_all();
85     }
86 };
87 
SetWatchDogTimeout(uint32_t timeoutMs)88 void WatchDog::SetWatchDogTimeout(uint32_t timeoutMs)
89 {
90     std::unique_lock<std::mutex> lock(mutex_);
91     timeoutMs_ = timeoutMs;
92 };
93 
Notify()94 void WatchDog::Notify()
95 {
96     std::unique_lock<std::mutex> lock(mutex_);
97     if (enable_) {
98         if (alarmed_) {
99             alarmed_ = false;
100             AlarmRecovery();
101             pause_ = false;
102             cond_.notify_all();
103         }
104 
105         count_++;
106         cond_.notify_all();
107     }
108 };
109 
Alarm()110 void WatchDog::Alarm()
111 {
112     MEDIA_LOGI("Alarm!");
113 };
114 
AlarmRecovery()115 void WatchDog::AlarmRecovery()
116 {
117     MEDIA_LOGI("AlarmRecovery!");
118 };
119 
WatchDogThread()120 void WatchDog::WatchDogThread()
121 {
122     while (true) {
123         std::unique_lock<std::mutex> lock(mutex_);
124 
125         // For pause/resume control, wait only when paused.
126         cond_.wait(lock, [this] {
127             return (enable_ == false) || (pause_ == false);
128         });
129 
130         if (paused_) {
131             paused_ = false;
132         }
133 
134         // For timeout detection.
135         cond_.wait_for(lock, std::chrono::milliseconds(timeoutMs_), [this] {
136             return (enable_ == false) || (pause_ == true) || (count_ > 0);
137         });
138 
139         if (enable_ == false) {
140             break;
141         }
142 
143         if (pause_ == true || paused_ == true) {
144             continue;
145         }
146 
147         if (count_ == 0) {
148             MEDIA_LOGI("Watchdog timeout!");
149             if (alarmed_ == false) {
150                 alarmed_ = true;
151                 Alarm();
152                 pause_ = true;
153             }
154         }
155 
156         count_ = 0;
157     }
158 }
159 } // namespace Media
160 } // namespace OHOS
161