blob: 085a726e5e6e38a3d2741a355af5de856a36f8ba [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 <stddef.h>
#include <new>
#include <kernel/mutex.h>
#include <lockdep/lockdep.h>
#if WITH_LOCK_DEP
#if kSchedulerLockSpinTracingEnabled || kLockNameTracingEnabled
constexpr size_t kExpectedMutexSize = 40;
#else
constexpr size_t kExpectedMutexSize = 32;
#endif
#else
#if kSchedulerLockSpinTracingEnabled || kLockNameTracingEnabled
constexpr size_t kExpectedMutexSize = 32;
#else
constexpr size_t kExpectedMutexSize = 24;
#endif
#endif
#if WITH_LOCK_DEP
using SystemLockType = lockdep::LockDep<void, Mutex>;
#else
using SystemLockType = Mutex;
#endif
static_assert(sizeof(SystemLockType) == kExpectedMutexSize,
"Rust KMutex size mismatch with C++ size");
static_assert(alignof(SystemLockType) == 8, "Mutex alignment must be exactly 8 bytes.");
static_assert(sizeof(lockdep::AcquiredLockEntry) == 40, "AcquiredLockEntry size mismatch");
static_assert(alignof(lockdep::AcquiredLockEntry) == 8,
"AcquiredLockEntry alignment must be exactly 8 bytes.");
extern "C" {
void cpp_mutex_init(Mutex* mutex) { new (mutex) Mutex(); }
void cpp_mutex_destroy(Mutex* mutex) { mutex->~Mutex(); }
void cpp_mutex_acquire(Mutex* mutex, lockdep::LockClassId lcid,
void* entry_storage) TA_NO_THREAD_SAFETY_ANALYSIS {
#if WITH_LOCK_DEP
if (lcid != nullptr && entry_storage != nullptr) {
auto* entry = new (entry_storage) lockdep::AcquiredLockEntry(mutex, lcid, 0);
lockdep::ThreadLockState::Get(lockdep::LockFlagsNone)->Acquire(entry);
}
#endif
mutex->Acquire();
}
void cpp_mutex_release(Mutex* mutex, void* entry_storage) TA_NO_THREAD_SAFETY_ANALYSIS {
#if WITH_LOCK_DEP
if (entry_storage != nullptr) {
auto* entry = static_cast<lockdep::AcquiredLockEntry*>(entry_storage);
lockdep::ThreadLockState::Get(lockdep::LockFlagsNone)->Release(entry);
entry->~AcquiredLockEntry();
}
#endif
mutex->Release();
}
void cpp_critical_mutex_init(CriticalMutex* mutex) { new (mutex) CriticalMutex(); }
void cpp_critical_mutex_destroy(CriticalMutex* mutex) { mutex->~CriticalMutex(); }
bool cpp_critical_mutex_acquire(CriticalMutex* mutex, lockdep::LockClassId lcid,
void* entry_storage) TA_NO_THREAD_SAFETY_ANALYSIS {
#if WITH_LOCK_DEP
if (lcid != nullptr && entry_storage != nullptr) {
auto* entry = new (entry_storage) lockdep::AcquiredLockEntry(mutex, lcid, 0);
lockdep::ThreadLockState::Get(lockdep::LockFlagsNone)->Acquire(entry);
}
#endif
auto should_clear = mutex->Acquire();
return should_clear == CriticalMutex::ShouldClear::Yes;
}
void cpp_critical_mutex_release(CriticalMutex* mutex, void* entry_storage,
bool should_clear) TA_NO_THREAD_SAFETY_ANALYSIS {
#if WITH_LOCK_DEP
if (entry_storage != nullptr) {
auto* entry = static_cast<lockdep::AcquiredLockEntry*>(entry_storage);
lockdep::ThreadLockState::Get(lockdep::LockFlagsNone)->Release(entry);
entry->~AcquiredLockEntry();
}
#endif
mutex->Release(should_clear ? CriticalMutex::ShouldClear::Yes : CriticalMutex::ShouldClear::No);
}
} // extern "C"