blob: 17bcadf37f307343cc5ae8ed6267cd826dbbe1e6 [file] [edit]
// Copyright 2026 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <atomic>
#include <condition_variable>
#include <cstdio>
#include <cstdlib>
#include <mutex>
#include <thread>
#include <lockdep/lock_class_state.h>
#include <lockdep/runtime_api.h>
#include <lockdep/thread_lock_state.h>
#if defined(__Fuchsia__)
#include "src/lib/debug/backtrace-request.h" // nogncheck
#elif defined(__linux__) || defined(__APPLE__)
#include <execinfo.h>
#include <unistd.h>
#endif
namespace lockdep {
namespace {
std::atomic<bool> loop_detection_graph_is_dirty{false};
std::mutex loop_detector_mutex;
std::condition_variable loop_detector_cv;
std::once_flag init_thread_once;
void LockDepThread() {
while (true) {
std::unique_lock<std::mutex> lock(loop_detector_mutex);
loop_detector_cv.wait_for(lock, std::chrono::seconds(2),
[] { return loop_detection_graph_is_dirty.load(); });
if (loop_detection_graph_is_dirty.exchange(false)) {
lockdep::LoopDetectionPass();
}
}
}
} // namespace
// System-defined hook to report detected lock validation failures.
void SystemLockValidationError(AcquiredLockEntry* lock_entry, AcquiredLockEntry* conflicting_entry,
ThreadLockState* state, void* caller_address, void* caller_frame,
LockResult result) {
std::fprintf(stderr, "====================================================\n");
std::fprintf(stderr, "LOCK DEP ERROR: Lock validation failed!\n");
std::fprintf(stderr, "Reason: %s\n", ToString(result));
std::fprintf(stderr, "Bad lock: name=%s order=%lu address=%p\n",
ValidatorLockClassState::GetName(lock_entry->id()),
static_cast<unsigned long>(lock_entry->order()), lock_entry->address());
std::fprintf(stderr, "Conflict: name=%s order=%lu address=%p\n",
ValidatorLockClassState::GetName(conflicting_entry->id()),
static_cast<unsigned long>(conflicting_entry->order()),
conflicting_entry->address());
std::fprintf(stderr, "caller=%p frame=%p\n", caller_address, caller_frame);
std::fprintf(stderr, "====================================================\n");
#if defined(__Fuchsia__)
backtrace_request_current_thread();
#elif defined(__linux__) || defined(__APPLE__)
void* array[128];
int size = backtrace(array, 128);
std::fprintf(stderr, "Backtrace:\n");
backtrace_symbols_fd(array, size, STDERR_FILENO);
#endif
}
// System-defined hook to abort the program due to a fatal lock violation.
void SystemLockValidationFatal(AcquiredLockEntry* lock_entry, ThreadLockState* state,
void* caller_address, void* caller_frame, LockResult result) {
std::fprintf(stderr, "====================================================\n");
std::fprintf(stderr, "LOCK DEP FATAL ERROR: Fatal lock violation detected!\n");
std::fprintf(stderr, "Reason: %s\n", ToString(result));
std::fprintf(stderr, "Lock: name=%s order=%lu address=%p\n",
ValidatorLockClassState::GetName(lock_entry->id()),
static_cast<unsigned long>(lock_entry->order()), lock_entry->address());
std::fprintf(stderr, "pc=%p stack frame=%p\n", caller_address, caller_frame);
std::fprintf(stderr, "====================================================\n");
#if defined(__Fuchsia__)
backtrace_request_current_thread();
#elif defined(__linux__) || defined(__APPLE__)
void* array[128];
int size = backtrace(array, 128);
std::fprintf(stderr, "Backtrace:\n");
backtrace_symbols_fd(array, size, STDERR_FILENO);
#endif
std::abort();
}
// System-defined hook to report detection of a circular lock dependency.
void SystemCircularLockDependencyDetected(ValidatorLockClassState* connected_set_root) {
std::fprintf(stderr, "====================================================\n");
std::fprintf(stderr, "LOCK DEP ERROR: Circular lock dependency detected:\n");
for (auto& node : ValidatorLockClassState::Iter()) {
if (node.connected_set() == connected_set_root) {
for (LockClassId dependency_id : node.dependency_set()) {
ValidatorLockClassState* dependency = ValidatorLockClassState::Get(dependency_id);
if (dependency->connected_set() == connected_set_root) {
std::fprintf(stderr, " %s -> %s\n", dependency->name(), node.name());
}
}
}
}
std::fprintf(stderr, "====================================================\n");
}
// System-defined hook that returns the ThreadLockState instance for the current
// thread.
ThreadLockState* SystemGetThreadLockState(LockFlags lock_flags) {
thread_local ThreadLockState thread_lock_state{};
return &thread_lock_state;
}
// System-defined hook that initializes the ThreadLockState for the current thread.
void SystemInitThreadLockState(ThreadLockState* state) {}
// System-defined hook that triggers a loop detection pass.
void SystemTriggerLoopDetection() {
loop_detection_graph_is_dirty.store(true);
std::call_once(init_thread_once, [] { std::thread(LockDepThread).detach(); });
loop_detector_cv.notify_one();
}
} // namespace lockdep