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 "core/task_ctx.h" 24 #include "dfx/log/ffrt_log_api.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,%{public}s], msg=%{public}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 TaskCtx* taskCtx = nullptr; 76 if (taskId >= TID_MAX) { 77 taskCtx = reinterpret_cast<TaskCtx*>(taskId); 78 #ifdef FFRT_CO_BACKTRACE_OH_ENABLE 79 std::string dumpInfo; 80 TaskCtx::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 mutexPrivate { 104 std::atomic<int> l; 105 #ifdef FFRT_MUTEX_DEADLOCK_CHECK 106 std::atomic<uintptr_t> owner; 107 #endif 108 fast_mutex wlock; 109 LinkedList list; 110 111 void wait(); 112 void wake(); 113 114 public: 115 #ifdef FFRT_MUTEX_DEADLOCK_CHECK mutexPrivate()116 mutexPrivate() : l(sync_detail::UNLOCK), owner(0) {} 117 #else 118 mutexPrivate() : l(sync_detail::UNLOCK) {} 119 #endif 120 mutexPrivate(mutexPrivate const &) = delete; 121 void operator = (mutexPrivate const &) = delete; 122 123 bool try_lock(); 124 void lock(); 125 void unlock(); 126 }; 127 } // namespace ffrt 128 129 #endif