1da853ecaSopenharmony_ci/* 2da853ecaSopenharmony_ci * Copyright (C) 2023 Huawei Device Co., Ltd. 3da853ecaSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4da853ecaSopenharmony_ci * you may not use this file except in compliance with the License. 5da853ecaSopenharmony_ci * You may obtain a copy of the License at 6da853ecaSopenharmony_ci * 7da853ecaSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8da853ecaSopenharmony_ci * 9da853ecaSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10da853ecaSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11da853ecaSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12da853ecaSopenharmony_ci * See the License for the specific language governing permissions and 13da853ecaSopenharmony_ci * limitations under the License. 14da853ecaSopenharmony_ci */ 15da853ecaSopenharmony_ci 16da853ecaSopenharmony_ci#include "avcodec_xcollie.h" 17da853ecaSopenharmony_ci#include <unistd.h> 18da853ecaSopenharmony_ci#include "avcodec_errors.h" 19da853ecaSopenharmony_ci#include "param_wrapper.h" 20da853ecaSopenharmony_ci#include "avcodec_dump_utils.h" 21da853ecaSopenharmony_ci#include "avcodec_log.h" 22da853ecaSopenharmony_ci#include "avcodec_sysevent.h" 23da853ecaSopenharmony_ci#ifdef HICOLLIE_ENABLE 24da853ecaSopenharmony_ci#include "xcollie/xcollie.h" 25da853ecaSopenharmony_ci#include "xcollie/xcollie_define.h" 26da853ecaSopenharmony_ci#endif 27da853ecaSopenharmony_ci 28da853ecaSopenharmony_cinamespace { 29da853ecaSopenharmony_ci constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_FRAMEWORK, "AVCodecXCollie"}; 30da853ecaSopenharmony_ci constexpr uint32_t DUMP_XCOLLIE_INDEX = 0x01000000; 31da853ecaSopenharmony_ci constexpr uint8_t DUMP_OFFSET_16 = 16; 32da853ecaSopenharmony_ci constexpr uint64_t COLLIE_INVALID_INDEX = 0; 33da853ecaSopenharmony_ci} 34da853ecaSopenharmony_ci 35da853ecaSopenharmony_cinamespace OHOS { 36da853ecaSopenharmony_cinamespace MediaAVCodec { 37da853ecaSopenharmony_ciAVCodecXCollie &AVCodecXCollie::GetInstance() 38da853ecaSopenharmony_ci{ 39da853ecaSopenharmony_ci static AVCodecXCollie instance; 40da853ecaSopenharmony_ci return instance; 41da853ecaSopenharmony_ci} 42da853ecaSopenharmony_ci 43da853ecaSopenharmony_civoid AVCodecXCollie::ServiceTimerCallback(void *data) 44da853ecaSopenharmony_ci{ 45da853ecaSopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 46da853ecaSopenharmony_ci threadDeadlockCount_++; 47da853ecaSopenharmony_ci std::string name = data != nullptr ? (char *)data : ""; 48da853ecaSopenharmony_ci 49da853ecaSopenharmony_ci AVCODEC_LOGE("Service task %{public}s timeout", name.c_str()); 50da853ecaSopenharmony_ci FaultEventWrite(FaultType::FAULT_TYPE_FREEZE, std::string("Service task ") + 51da853ecaSopenharmony_ci name + std::string(" timeout"), "Service"); 52da853ecaSopenharmony_ci 53da853ecaSopenharmony_ci static constexpr uint32_t threshold = 1; // >= 1 Restart service 54da853ecaSopenharmony_ci if (threadDeadlockCount_ >= threshold) { 55da853ecaSopenharmony_ci FaultEventWrite(FaultType::FAULT_TYPE_FREEZE, 56da853ecaSopenharmony_ci "Process timeout, AVCodec service process exit.", "Service"); 57da853ecaSopenharmony_ci AVCODEC_LOGF("Process timeout, AVCodec service process exit."); 58da853ecaSopenharmony_ci _exit(-1); 59da853ecaSopenharmony_ci } 60da853ecaSopenharmony_ci} 61da853ecaSopenharmony_ci 62da853ecaSopenharmony_civoid AVCodecXCollie::ClientTimerCallback(void *data) 63da853ecaSopenharmony_ci{ 64da853ecaSopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 65da853ecaSopenharmony_ci std::string name = data != nullptr ? (char *)data : ""; 66da853ecaSopenharmony_ci AVCODEC_LOGE("Client task %{public}s timeout", name.c_str()); 67da853ecaSopenharmony_ci FaultEventWrite(FaultType::FAULT_TYPE_FREEZE, std::string("Client task ") + 68da853ecaSopenharmony_ci name + std::string(" timeout"), "Client"); 69da853ecaSopenharmony_ci} 70da853ecaSopenharmony_ci 71da853ecaSopenharmony_ciint32_t AVCodecXCollie::Dump(int32_t fd) 72da853ecaSopenharmony_ci{ 73da853ecaSopenharmony_ci if (dfxDumper_.empty()) { 74da853ecaSopenharmony_ci return AVCS_ERR_OK; 75da853ecaSopenharmony_ci } 76da853ecaSopenharmony_ci 77da853ecaSopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 78da853ecaSopenharmony_ci std::string dumpString = "[AVCodec_XCollie]\n"; 79da853ecaSopenharmony_ci AVCodecDumpControler dumpControler; 80da853ecaSopenharmony_ci uint32_t dumperIndex = 1; 81da853ecaSopenharmony_ci for (const auto &iter : dfxDumper_) { 82da853ecaSopenharmony_ci dumpControler.AddInfo(DUMP_XCOLLIE_INDEX + (dumperIndex << DUMP_OFFSET_16), "Timer_Name", iter.second.second); 83da853ecaSopenharmony_ci dumperIndex++; 84da853ecaSopenharmony_ci } 85da853ecaSopenharmony_ci dumpControler.GetDumpString(dumpString); 86da853ecaSopenharmony_ci if (fd != -1) { 87da853ecaSopenharmony_ci write(fd, dumpString.c_str(), dumpString.size()); 88da853ecaSopenharmony_ci dumpString.clear(); 89da853ecaSopenharmony_ci } 90da853ecaSopenharmony_ci return AVCS_ERR_OK; 91da853ecaSopenharmony_ci} 92da853ecaSopenharmony_ci 93da853ecaSopenharmony_ci 94da853ecaSopenharmony_ciuint64_t AVCodecXCollie::SetTimer(const std::string &name, bool isService, bool recovery, uint32_t timeout) 95da853ecaSopenharmony_ci{ 96da853ecaSopenharmony_ci#ifdef HICOLLIE_ENABLE 97da853ecaSopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 98da853ecaSopenharmony_ci 99da853ecaSopenharmony_ci std::function<void (void *)> func; 100da853ecaSopenharmony_ci if (isService) { 101da853ecaSopenharmony_ci func = [this](void *data) { this->ServiceTimerCallback(data); }; 102da853ecaSopenharmony_ci } else { 103da853ecaSopenharmony_ci func = [this](void *data) { this->ClientTimerCallback(data); }; 104da853ecaSopenharmony_ci } 105da853ecaSopenharmony_ci 106da853ecaSopenharmony_ci unsigned int flag = HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_NOOP; 107da853ecaSopenharmony_ci if (recovery) { 108da853ecaSopenharmony_ci flag |= HiviewDFX::XCOLLIE_FLAG_RECOVERY; 109da853ecaSopenharmony_ci } 110da853ecaSopenharmony_ci uint64_t tempIndex = dumperIndex_++; 111da853ecaSopenharmony_ci dfxDumper_.emplace(tempIndex, std::pair<int32_t, std::string>(HiviewDFX::INVALID_ID, name)); 112da853ecaSopenharmony_ci int32_t id = HiviewDFX::XCollie::GetInstance().SetTimer(name, 113da853ecaSopenharmony_ci timeout, func, (void *)dfxDumper_[tempIndex].second.c_str(), flag); 114da853ecaSopenharmony_ci if (id == HiviewDFX::INVALID_ID) { 115da853ecaSopenharmony_ci auto it = dfxDumper_.find(tempIndex); 116da853ecaSopenharmony_ci if (it != dfxDumper_.end()) { 117da853ecaSopenharmony_ci dfxDumper_.erase(it); 118da853ecaSopenharmony_ci return COLLIE_INVALID_INDEX; 119da853ecaSopenharmony_ci } 120da853ecaSopenharmony_ci } 121da853ecaSopenharmony_ci dfxDumper_[tempIndex].first = id; 122da853ecaSopenharmony_ci return tempIndex; 123da853ecaSopenharmony_ci#else 124da853ecaSopenharmony_ci (void)dumperIndex_; 125da853ecaSopenharmony_ci return COLLIE_INVALID_INDEX; 126da853ecaSopenharmony_ci#endif 127da853ecaSopenharmony_ci} 128da853ecaSopenharmony_ci 129da853ecaSopenharmony_civoid AVCodecXCollie::CancelTimer(uint64_t index) 130da853ecaSopenharmony_ci{ 131da853ecaSopenharmony_ci#ifdef HICOLLIE_ENABLE 132da853ecaSopenharmony_ci if (index == COLLIE_INVALID_INDEX) { 133da853ecaSopenharmony_ci return; 134da853ecaSopenharmony_ci } 135da853ecaSopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 136da853ecaSopenharmony_ci auto it = dfxDumper_.find(index); 137da853ecaSopenharmony_ci if (it == dfxDumper_.end()) { 138da853ecaSopenharmony_ci return; 139da853ecaSopenharmony_ci } 140da853ecaSopenharmony_ci int32_t id = it->second.first; 141da853ecaSopenharmony_ci dfxDumper_.erase(it); 142da853ecaSopenharmony_ci return HiviewDFX::XCollie::GetInstance().CancelTimer(id); 143da853ecaSopenharmony_ci#else 144da853ecaSopenharmony_ci (void)index; 145da853ecaSopenharmony_ci return; 146da853ecaSopenharmony_ci#endif 147da853ecaSopenharmony_ci} 148da853ecaSopenharmony_ci} // namespace MediaAVCodec 149da853ecaSopenharmony_ci} // namespace OHOS