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 #ifndef _MUTEX_PRIVATE_H_ 17 #define _MUTEX_PRIVATE_H_ 18 19 #include "sync/sync.h" 20 21 #ifdef FFRT_MUTEX_DEADLOCK_CHECK 22 #include "util/graph_check.h" 23 #include "dfx/log/ffrt_log_api.h" 24 #include "tm/cpu_task.h" 25 26 #define TID_MAX (0x400000) 27 #endif 28 #ifdef FFRT_OH_EVENT_RECORD 29 #include "hisysevent.h" 30 #endif 31 namespace ffrt { 32 #ifdef FFRT_MUTEX_DEADLOCK_CHECK 33 class MutexGraph { 34 std::mutex mutex; 35 GraphCheckCyclic graph; 36 37 public: Instance()38 static MutexGraph& Instance() 39 { 40 static MutexGraph mgraph; 41 return mgraph; 42 } 43 SendEvent(const std::string & msg,const std::string & eventName)44 void SendEvent(const std::string &msg, const std::string& eventName) 45 { 46 #ifdef FFRT_OH_EVENT_RECORD 47 int32_t pid = getpid(); 48 int32_t gid = getgid(); 49 int32_t uid = getuid(); 50 time_t cur_time = time(nullptr); 51 std::string sendMsg = std::string((ctime(&cur_time) == nullptr) ? "" : ctime(&cur_time)) + 52 "\n" + msg + "\n"; 53 54 HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::FFRT, eventName, 55 OHOS::HiviewDFX::HiSysEvent::EventType::FAULT, 56 "PID", pid, 57 "TGID", gid, 58 "UID", uid, 59 "MODULE_NAME", "ffrt", 60 "PROCESS_NAME", "ffrt", 61 "MSG", sendMsg); 62 FFRT_LOGE("send event [FRAMEWORK,%s], msg=%s", eventName.c_str(), msg.c_str()); 63 #endif 64 } 65 AddNode(uint64_t task,uint64_t ownerTask,bool edge)66 void AddNode(uint64_t task, uint64_t ownerTask, bool edge) 67 { 68 std::lock_guard<std::mutex> lg{mutex}; 69 graph.AddVetexByLabel(task); 70 if (edge) { 71 graph.AddEdgeByLabel(ownerTask, task); 72 if (graph.IsCyclic()) { 73 std::string dlockInfo = "A possible mutex deadlock detected!\n"; 74 for (uint64_t taskId : {ownerTask, task}) { 75 CPUEUTask* taskCtx = nullptr; 76 if (taskId >= TID_MAX) { 77 taskCtx = reinterpret_cast<CPUEUTask*>(taskId); 78 #ifdef FFRT_CO_BACKTRACE_OH_ENABLE 79 std::string dumpInfo; 80 CPUEUTask::DumpTask(taskCtx, dumpInfo, 1); 81 dlockInfo += dumpInfo; 82 #endif 83 } else { 84 std::string threadInfo = "The linux thread id is "; 85 threadInfo += std::to_string(taskId); 86 threadInfo.append("\n"); 87 dlockInfo += threadInfo; 88 } 89 } 90 SendEvent(dlockInfo, "TASK_DEADLOCK"); 91 } 92 } 93 } 94 RemoveNode(uint64_t task)95 void RemoveNode(uint64_t task) 96 { 97 std::lock_guard<std::mutex> lg{mutex}; 98 graph.RemoveEdgeByLabel(task); 99 } 100 }; 101 #endif 102 103 class mutexBase { 104 public: 105 mutexBase() = default; 106 virtual ~mutexBase() = default; lock()107 virtual void lock() {} unlock()108 virtual void unlock() {} try_lock()109 virtual bool try_lock() {return false;} 110 }; 111 112 class mutexPrivate : public mutexBase { 113 std::atomic<int> l; 114 #ifdef FFRT_MUTEX_DEADLOCK_CHECK 115 std::atomic<uintptr_t> owner; 116 #endif 117 fast_mutex wlock; 118 LinkedList list; 119 120 void wait(); 121 void wake(); 122 123 public: 124 #ifdef FFRT_MUTEX_DEADLOCK_CHECK mutexPrivate()125 mutexPrivate() : l(sync_detail::UNLOCK), owner(0) {} 126 #else 127 mutexPrivate() : l(sync_detail::UNLOCK) {} 128 #endif 129 mutexPrivate(mutexPrivate const &) = delete; 130 void operator = (mutexPrivate const &) = delete; 131 132 bool try_lock() override; 133 void lock() override; 134 void unlock() override; 135 }; 136 137 class RecursiveMutexPrivate : public mutexBase { 138 public: 139 void lock() override; 140 void unlock() override; 141 bool try_lock() override; 142 143 RecursiveMutexPrivate() = default; 144 ~RecursiveMutexPrivate() = default; 145 RecursiveMutexPrivate(RecursiveMutexPrivate const&) = delete; 146 void operator = (RecursiveMutexPrivate const&) = delete; 147 148 private: 149 std::pair<uint64_t, uint32_t> taskLockNums = std::make_pair(UINT64_MAX, 0); 150 fast_mutex fMutex; 151 mutexPrivate mt; 152 }; 153 154 } // namespace ffrt 155 156 #endif 157