14d6c458bSopenharmony_ci/*
24d6c458bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
34d6c458bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44d6c458bSopenharmony_ci * you may not use this file except in compliance with the License.
54d6c458bSopenharmony_ci * You may obtain a copy of the License at
64d6c458bSopenharmony_ci *
74d6c458bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84d6c458bSopenharmony_ci *
94d6c458bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104d6c458bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114d6c458bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124d6c458bSopenharmony_ci * See the License for the specific language governing permissions and
134d6c458bSopenharmony_ci * limitations under the License.
144d6c458bSopenharmony_ci */
154d6c458bSopenharmony_ci
164d6c458bSopenharmony_ci#include <sstream>
174d6c458bSopenharmony_ci
184d6c458bSopenharmony_ci#include "deadlock_helpers.h"
194d6c458bSopenharmony_ci#include "common.h"
204d6c458bSopenharmony_ci#include "graph.h"
214d6c458bSopenharmony_ci
224d6c458bSopenharmony_cinamespace Commonlibrary::Concurrent::LocksModule {
234d6c458bSopenharmony_ci
244d6c458bSopenharmony_cistd::string CreateDeadlockWarningMessage(DeadlockInfo &&deadlock)
254d6c458bSopenharmony_ci{
264d6c458bSopenharmony_ci    std::stringstream s;
274d6c458bSopenharmony_ci    auto vertexPrinter = [](tid_t tid) { return "TID " + std::to_string(tid); };
284d6c458bSopenharmony_ci    auto edgePrinter = [](const AsyncLockDependency *edata) { return " <-- lock {" + edata->name + "} -- WAITED BY "; };
294d6c458bSopenharmony_ci    s << "!!! DEADLOCK WARNING !!!\n"
304d6c458bSopenharmony_ci      << LockGraph::CycleAsString(deadlock, "Possible deadlock: ", "\n", vertexPrinter, edgePrinter);
314d6c458bSopenharmony_ci    return s.str();
324d6c458bSopenharmony_ci}
334d6c458bSopenharmony_ci
344d6c458bSopenharmony_cistd::string CreateFullLockInfosMessage(tid_t targetTid, std::vector<AsyncLockDependency> &&dependencies,
354d6c458bSopenharmony_ci                                       DeadlockInfo &&deadlock)
364d6c458bSopenharmony_ci{
374d6c458bSopenharmony_ci    std::stringstream s;
384d6c458bSopenharmony_ci    s << "\nThread's async locks information:\n";
394d6c458bSopenharmony_ci    for (auto &maybeHeld : dependencies) {
404d6c458bSopenharmony_ci        if ((maybeHeld.holderTid == targetTid) && (maybeHeld.waiterTid == INVALID_TID)) {
414d6c458bSopenharmony_ci            s << "HELD: lock {" + maybeHeld.name + "} , taken at:\n" + maybeHeld.creationStacktrace + "\n";
424d6c458bSopenharmony_ci        }
434d6c458bSopenharmony_ci    }
444d6c458bSopenharmony_ci    for (auto &maybeWaiting : dependencies) {
454d6c458bSopenharmony_ci        if (maybeWaiting.waiterTid == targetTid) {
464d6c458bSopenharmony_ci            s << "WAITING: lock {" + maybeWaiting.name + "} , taken at:\n" + maybeWaiting.creationStacktrace + "\n";
474d6c458bSopenharmony_ci        }
484d6c458bSopenharmony_ci    }
494d6c458bSopenharmony_ci    if (!deadlock.IsEmpty()) {
504d6c458bSopenharmony_ci        s << CreateDeadlockWarningMessage(std::move(deadlock));
514d6c458bSopenharmony_ci    } else {
524d6c458bSopenharmony_ci        s << "No deadlocks detected.\n";
534d6c458bSopenharmony_ci    }
544d6c458bSopenharmony_ci    return s.str();
554d6c458bSopenharmony_ci}
564d6c458bSopenharmony_ci
574d6c458bSopenharmony_ciDeadlockInfo CheckDeadlocks(const std::vector<AsyncLockDependency> &dependencies)
584d6c458bSopenharmony_ci{
594d6c458bSopenharmony_ci    LockGraph::AdjacencyList adjlist;
604d6c458bSopenharmony_ci    for (auto &dep : dependencies) {
614d6c458bSopenharmony_ci        if (dep.waiterTid == INVALID_TID) {
624d6c458bSopenharmony_ci            // this is the "held only" edge, skip
634d6c458bSopenharmony_ci            continue;
644d6c458bSopenharmony_ci        }
654d6c458bSopenharmony_ci        adjlist.push_back(std::make_tuple(dep.waiterTid, dep.holderTid, &dep));
664d6c458bSopenharmony_ci    }
674d6c458bSopenharmony_ci    LockGraph g(std::move(adjlist));
684d6c458bSopenharmony_ci    return g.FindFirstCycle();
694d6c458bSopenharmony_ci}
704d6c458bSopenharmony_ci
714d6c458bSopenharmony_ci}  // namespace Commonlibrary::Concurrent::LocksModule