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 "avcodec_xcollie.h" 17#include <unistd.h> 18#include "avcodec_errors.h" 19#include "param_wrapper.h" 20#include "avcodec_dump_utils.h" 21#include "avcodec_log.h" 22#include "avcodec_sysevent.h" 23#ifdef HICOLLIE_ENABLE 24#include "xcollie/xcollie.h" 25#include "xcollie/xcollie_define.h" 26#endif 27 28namespace { 29 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_FRAMEWORK, "AVCodecXCollie"}; 30 constexpr uint32_t DUMP_XCOLLIE_INDEX = 0x01000000; 31 constexpr uint8_t DUMP_OFFSET_16 = 16; 32 constexpr uint64_t COLLIE_INVALID_INDEX = 0; 33} 34 35namespace OHOS { 36namespace MediaAVCodec { 37AVCodecXCollie &AVCodecXCollie::GetInstance() 38{ 39 static AVCodecXCollie instance; 40 return instance; 41} 42 43void AVCodecXCollie::ServiceTimerCallback(void *data) 44{ 45 std::lock_guard<std::mutex> lock(mutex_); 46 threadDeadlockCount_++; 47 std::string name = data != nullptr ? (char *)data : ""; 48 49 AVCODEC_LOGE("Service task %{public}s timeout", name.c_str()); 50 FaultEventWrite(FaultType::FAULT_TYPE_FREEZE, std::string("Service task ") + 51 name + std::string(" timeout"), "Service"); 52 53 static constexpr uint32_t threshold = 1; // >= 1 Restart service 54 if (threadDeadlockCount_ >= threshold) { 55 FaultEventWrite(FaultType::FAULT_TYPE_FREEZE, 56 "Process timeout, AVCodec service process exit.", "Service"); 57 AVCODEC_LOGF("Process timeout, AVCodec service process exit."); 58 _exit(-1); 59 } 60} 61 62void AVCodecXCollie::ClientTimerCallback(void *data) 63{ 64 std::lock_guard<std::mutex> lock(mutex_); 65 std::string name = data != nullptr ? (char *)data : ""; 66 AVCODEC_LOGE("Client task %{public}s timeout", name.c_str()); 67 FaultEventWrite(FaultType::FAULT_TYPE_FREEZE, std::string("Client task ") + 68 name + std::string(" timeout"), "Client"); 69} 70 71int32_t AVCodecXCollie::Dump(int32_t fd) 72{ 73 if (dfxDumper_.empty()) { 74 return AVCS_ERR_OK; 75 } 76 77 std::lock_guard<std::mutex> lock(mutex_); 78 std::string dumpString = "[AVCodec_XCollie]\n"; 79 AVCodecDumpControler dumpControler; 80 uint32_t dumperIndex = 1; 81 for (const auto &iter : dfxDumper_) { 82 dumpControler.AddInfo(DUMP_XCOLLIE_INDEX + (dumperIndex << DUMP_OFFSET_16), "Timer_Name", iter.second.second); 83 dumperIndex++; 84 } 85 dumpControler.GetDumpString(dumpString); 86 if (fd != -1) { 87 write(fd, dumpString.c_str(), dumpString.size()); 88 dumpString.clear(); 89 } 90 return AVCS_ERR_OK; 91} 92 93 94uint64_t AVCodecXCollie::SetTimer(const std::string &name, bool isService, bool recovery, uint32_t timeout) 95{ 96#ifdef HICOLLIE_ENABLE 97 std::lock_guard<std::mutex> lock(mutex_); 98 99 std::function<void (void *)> func; 100 if (isService) { 101 func = [this](void *data) { this->ServiceTimerCallback(data); }; 102 } else { 103 func = [this](void *data) { this->ClientTimerCallback(data); }; 104 } 105 106 unsigned int flag = HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_NOOP; 107 if (recovery) { 108 flag |= HiviewDFX::XCOLLIE_FLAG_RECOVERY; 109 } 110 uint64_t tempIndex = dumperIndex_++; 111 dfxDumper_.emplace(tempIndex, std::pair<int32_t, std::string>(HiviewDFX::INVALID_ID, name)); 112 int32_t id = HiviewDFX::XCollie::GetInstance().SetTimer(name, 113 timeout, func, (void *)dfxDumper_[tempIndex].second.c_str(), flag); 114 if (id == HiviewDFX::INVALID_ID) { 115 auto it = dfxDumper_.find(tempIndex); 116 if (it != dfxDumper_.end()) { 117 dfxDumper_.erase(it); 118 return COLLIE_INVALID_INDEX; 119 } 120 } 121 dfxDumper_[tempIndex].first = id; 122 return tempIndex; 123#else 124 (void)dumperIndex_; 125 return COLLIE_INVALID_INDEX; 126#endif 127} 128 129void AVCodecXCollie::CancelTimer(uint64_t index) 130{ 131#ifdef HICOLLIE_ENABLE 132 if (index == COLLIE_INVALID_INDEX) { 133 return; 134 } 135 std::lock_guard<std::mutex> lock(mutex_); 136 auto it = dfxDumper_.find(index); 137 if (it == dfxDumper_.end()) { 138 return; 139 } 140 int32_t id = it->second.first; 141 dfxDumper_.erase(it); 142 return HiviewDFX::XCollie::GetInstance().CancelTimer(id); 143#else 144 (void)index; 145 return; 146#endif 147} 148} // namespace MediaAVCodec 149} // namespace OHOS