From 19fcec84d8d7d21e796c7624e521b60d28ee21ed Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 20:45:59 +0200 Subject: Adding upstream version 16.2.11+ds. Signed-off-by: Daniel Baumann --- src/common/ceph_mutex.h | 189 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 src/common/ceph_mutex.h (limited to 'src/common/ceph_mutex.h') diff --git a/src/common/ceph_mutex.h b/src/common/ceph_mutex.h new file mode 100644 index 000000000..81777c7db --- /dev/null +++ b/src/common/ceph_mutex.h @@ -0,0 +1,189 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#pragma once + +#include +#include "common/containers.h" + +// What and why +// ============ +// +// For general code making use of mutexes, use these ceph:: types. +// The key requirement is that you make use of the ceph::make_mutex() +// and make_recursive_mutex() factory methods, which take a string +// naming the mutex for the purposes of the lockdep debug variant. + +#if defined(WITH_SEASTAR) && !defined(WITH_ALIEN) + +namespace ceph { + // an empty class satisfying the mutex concept + struct dummy_mutex { + void lock() {} + bool try_lock() { + return true; + } + void unlock() {} + void lock_shared() {} + void unlock_shared() {} + }; + + struct dummy_shared_mutex : dummy_mutex { + void lock_shared() {} + void unlock_shared() {} + }; + + using mutex = dummy_mutex; + using recursive_mutex = dummy_mutex; + using shared_mutex = dummy_shared_mutex; + // in seastar, we should use a difference interface for enforcing the + // semantics of condition_variable + + template + dummy_mutex make_mutex(Args&& ...args) { + return {}; + } + + template + recursive_mutex make_recursive_mutex(Args&& ...args) { + return {}; + } + + template + shared_mutex make_shared_mutex(Args&& ...args) { + return {}; + } + + #define ceph_mutex_is_locked(m) true + #define ceph_mutex_is_locked_by_me(m) true +} + +#else // defined (WITH_SEASTAR) && !defined(WITH_ALIEN) +// +// For legacy Mutex users that passed recursive=true, use +// ceph::make_recursive_mutex. For legacy Mutex users that passed +// lockdep=false, use std::mutex directly. + +#ifdef CEPH_DEBUG_MUTEX + +// ============================================================================ +// debug (lockdep-capable, various sanity checks and asserts) +// ============================================================================ +// +// Note: this is known to cause deadlocks on Windows because +// of the winpthreads shared mutex implementation. + +#include "common/condition_variable_debug.h" +#include "common/mutex_debug.h" +#include "common/shared_mutex_debug.h" + +namespace ceph { + typedef ceph::mutex_debug mutex; + typedef ceph::mutex_recursive_debug recursive_mutex; + typedef ceph::condition_variable_debug condition_variable; + typedef ceph::shared_mutex_debug shared_mutex; + + // pass arguments to mutex_debug ctor + template + mutex make_mutex(Args&& ...args) { + return {std::forward(args)...}; + } + + // pass arguments to recursive_mutex_debug ctor + template + recursive_mutex make_recursive_mutex(Args&& ...args) { + return {std::forward(args)...}; + } + + // pass arguments to shared_mutex_debug ctor + template + shared_mutex make_shared_mutex(Args&& ...args) { + return {std::forward(args)...}; + } + + // debug methods + #define ceph_mutex_is_locked(m) ((m).is_locked()) + #define ceph_mutex_is_not_locked(m) (!(m).is_locked()) + #define ceph_mutex_is_rlocked(m) ((m).is_rlocked()) + #define ceph_mutex_is_wlocked(m) ((m).is_wlocked()) + #define ceph_mutex_is_locked_by_me(m) ((m).is_locked_by_me()) + #define ceph_mutex_is_not_locked_by_me(m) (!(m).is_locked_by_me()) +} + +#else + +// ============================================================================ +// release (fast and minimal) +// ============================================================================ + +#include +#include + +// The winpthreads shared mutex implementation is broken. +// We'll use boost::shared_mutex instead. +// https://github.com/msys2/MINGW-packages/issues/3319 +#if __MINGW32__ +#include +#else +#include +#endif + +namespace ceph { + + typedef std::mutex mutex; + typedef std::recursive_mutex recursive_mutex; + typedef std::condition_variable condition_variable; + +#if __MINGW32__ + typedef boost::shared_mutex shared_mutex; +#else + typedef std::shared_mutex shared_mutex; +#endif + + // discard arguments to make_mutex (they are for debugging only) + template + mutex make_mutex(Args&& ...args) { + return {}; + } + template + recursive_mutex make_recursive_mutex(Args&& ...args) { + return {}; + } + template + shared_mutex make_shared_mutex(Args&& ...args) { + return {}; + } + + // debug methods. Note that these can blindly return true + // because any code that does anything other than assert these + // are true is broken. + #define ceph_mutex_is_locked(m) true + #define ceph_mutex_is_not_locked(m) true + #define ceph_mutex_is_rlocked(m) true + #define ceph_mutex_is_wlocked(m) true + #define ceph_mutex_is_locked_by_me(m) true + #define ceph_mutex_is_not_locked_by_me(m) true + +} + +#endif // CEPH_DEBUG_MUTEX + +#endif // WITH_SEASTAR + +namespace ceph { + +template +ceph::containers::tiny_vector make_lock_container( + const std::size_t num_instances, + LockFactoryT&& lock_factory) +{ + return { + num_instances, [&](const std::size_t i, auto emplacer) { + // this will be called `num_instances` times + new (emplacer.data()) LockT {lock_factory(i)}; + } + }; +} +} // namespace ceph + -- cgit v1.2.3