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