1049e185fSopenharmony_ci/* 2049e185fSopenharmony_ci * Copyright (C) 2023 Huawei Device Co., Ltd. 3049e185fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4049e185fSopenharmony_ci * you may not use this file except in compliance with the License. 5049e185fSopenharmony_ci * You may obtain a copy of the License at 6049e185fSopenharmony_ci * 7049e185fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8049e185fSopenharmony_ci * 9049e185fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10049e185fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11049e185fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12049e185fSopenharmony_ci * See the License for the specific language governing permissions and 13049e185fSopenharmony_ci * limitations under the License. 14049e185fSopenharmony_ci */ 15049e185fSopenharmony_ci 16049e185fSopenharmony_ci#include "watchdog.h" 17049e185fSopenharmony_ci#include <mutex> 18049e185fSopenharmony_ci#include <thread> 19049e185fSopenharmony_ci 20049e185fSopenharmony_cinamespace { 21049e185fSopenharmony_ci constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_PLAYER, "watchdog"}; 22049e185fSopenharmony_ci} 23049e185fSopenharmony_ci 24049e185fSopenharmony_cinamespace OHOS { 25049e185fSopenharmony_cinamespace Media { 26049e185fSopenharmony_ciWatchDog::~WatchDog() 27049e185fSopenharmony_ci{ 28049e185fSopenharmony_ci DisableWatchDog(); 29049e185fSopenharmony_ci} 30049e185fSopenharmony_ci 31049e185fSopenharmony_civoid WatchDog::EnableWatchDog() 32049e185fSopenharmony_ci{ 33049e185fSopenharmony_ci while (true) { 34049e185fSopenharmony_ci std::unique_lock<std::mutex> lock(mutex_); 35049e185fSopenharmony_ci if (enable_) { 36049e185fSopenharmony_ci return; 37049e185fSopenharmony_ci } 38049e185fSopenharmony_ci 39049e185fSopenharmony_ci if (disabling.load()) { 40049e185fSopenharmony_ci continue; // Wait for disable execution to finish. 41049e185fSopenharmony_ci } 42049e185fSopenharmony_ci 43049e185fSopenharmony_ci enable_ = true; 44049e185fSopenharmony_ci thread_ = std::make_unique<std::thread>([this] () -> void { this->WatchDogThread(); }); 45049e185fSopenharmony_ci break; 46049e185fSopenharmony_ci } 47049e185fSopenharmony_ci} 48049e185fSopenharmony_ci 49049e185fSopenharmony_civoid WatchDog::DisableWatchDog() 50049e185fSopenharmony_ci{ 51049e185fSopenharmony_ci std::unique_lock<std::mutex> lock(mutex_); 52049e185fSopenharmony_ci if (disabling.load() == false) { 53049e185fSopenharmony_ci disabling.store(true); 54049e185fSopenharmony_ci enable_ = false; 55049e185fSopenharmony_ci cond_.notify_all(); 56049e185fSopenharmony_ci lock.unlock(); // Make the thread acquire the lock and exit. 57049e185fSopenharmony_ci if (thread_ != nullptr && thread_->joinable()) { 58049e185fSopenharmony_ci thread_->join(); 59049e185fSopenharmony_ci thread_.reset(); 60049e185fSopenharmony_ci thread_ = nullptr; 61049e185fSopenharmony_ci } 62049e185fSopenharmony_ci 63049e185fSopenharmony_ci // It may be changed by thread. Assign value after thread recycle. 64049e185fSopenharmony_ci pause_ = false; 65049e185fSopenharmony_ci alarmed_ = false; 66049e185fSopenharmony_ci disabling.store(false); 67049e185fSopenharmony_ci } 68049e185fSopenharmony_ci} 69049e185fSopenharmony_ci 70049e185fSopenharmony_civoid WatchDog::PauseWatchDog() 71049e185fSopenharmony_ci{ 72049e185fSopenharmony_ci std::unique_lock<std::mutex> lock(mutex_); 73049e185fSopenharmony_ci if (enable_) { 74049e185fSopenharmony_ci pause_ = true; 75049e185fSopenharmony_ci paused_ = true; 76049e185fSopenharmony_ci cond_.notify_all(); 77049e185fSopenharmony_ci } 78049e185fSopenharmony_ci} 79049e185fSopenharmony_ci 80049e185fSopenharmony_civoid WatchDog::ResumeWatchDog() 81049e185fSopenharmony_ci{ 82049e185fSopenharmony_ci std::unique_lock<std::mutex> lock(mutex_); 83049e185fSopenharmony_ci if (enable_) { 84049e185fSopenharmony_ci pause_ = false; 85049e185fSopenharmony_ci cond_.notify_all(); 86049e185fSopenharmony_ci } 87049e185fSopenharmony_ci} 88049e185fSopenharmony_ci 89049e185fSopenharmony_civoid WatchDog::Notify() 90049e185fSopenharmony_ci{ 91049e185fSopenharmony_ci std::unique_lock<std::mutex> lock(mutex_); 92049e185fSopenharmony_ci if (enable_) { 93049e185fSopenharmony_ci if (alarmed_) { 94049e185fSopenharmony_ci alarmed_ = false; 95049e185fSopenharmony_ci AlarmRecovery(); 96049e185fSopenharmony_ci pause_ = false; 97049e185fSopenharmony_ci cond_.notify_all(); 98049e185fSopenharmony_ci } 99049e185fSopenharmony_ci 100049e185fSopenharmony_ci count_++; 101049e185fSopenharmony_ci cond_.notify_all(); 102049e185fSopenharmony_ci } 103049e185fSopenharmony_ci} 104049e185fSopenharmony_ci 105049e185fSopenharmony_civoid WatchDog::Alarm() 106049e185fSopenharmony_ci{ 107049e185fSopenharmony_ci MEDIA_LOGI("Alarm!"); 108049e185fSopenharmony_ci} 109049e185fSopenharmony_ci 110049e185fSopenharmony_civoid WatchDog::AlarmRecovery() 111049e185fSopenharmony_ci{ 112049e185fSopenharmony_ci MEDIA_LOGI("AlarmRecovery!"); 113049e185fSopenharmony_ci} 114049e185fSopenharmony_ci 115049e185fSopenharmony_civoid WatchDog::WatchDogThread() 116049e185fSopenharmony_ci{ 117049e185fSopenharmony_ci while (true) { 118049e185fSopenharmony_ci std::unique_lock<std::mutex> lock(mutex_); 119049e185fSopenharmony_ci 120049e185fSopenharmony_ci // For pause/resume control, wait only when paused. 121049e185fSopenharmony_ci cond_.wait(lock, [this] { 122049e185fSopenharmony_ci return (enable_ == false) || (pause_ == false); 123049e185fSopenharmony_ci }); 124049e185fSopenharmony_ci 125049e185fSopenharmony_ci if (paused_) { 126049e185fSopenharmony_ci paused_ = false; 127049e185fSopenharmony_ci } 128049e185fSopenharmony_ci 129049e185fSopenharmony_ci // For timeout detection. 130049e185fSopenharmony_ci cond_.wait_for(lock, std::chrono::milliseconds(timeoutMs_), [this] { 131049e185fSopenharmony_ci return (enable_ == false) || (pause_ == true) || (count_ > 0); 132049e185fSopenharmony_ci }); 133049e185fSopenharmony_ci 134049e185fSopenharmony_ci if (enable_ == false) { 135049e185fSopenharmony_ci break; 136049e185fSopenharmony_ci } 137049e185fSopenharmony_ci 138049e185fSopenharmony_ci if (pause_ == true || paused_ == true) { 139049e185fSopenharmony_ci continue; 140049e185fSopenharmony_ci } 141049e185fSopenharmony_ci 142049e185fSopenharmony_ci if (count_ == 0) { 143049e185fSopenharmony_ci MEDIA_LOGI("Watchdog timeout!"); 144049e185fSopenharmony_ci if (alarmed_ == false) { 145049e185fSopenharmony_ci alarmed_ = true; 146049e185fSopenharmony_ci Alarm(); 147049e185fSopenharmony_ci pause_ = true; 148049e185fSopenharmony_ci } 149049e185fSopenharmony_ci } 150049e185fSopenharmony_ci 151049e185fSopenharmony_ci count_ = 0; 152049e185fSopenharmony_ci } 153049e185fSopenharmony_ci} 154049e185fSopenharmony_ci} // namespace Media 155049e185fSopenharmony_ci} // namespace OHOS 156