diff --git a/src/common/buffer.cc b/src/common/buffer.cc index 01a3dc82f0d..a77be1e7943 100644 --- a/src/common/buffer.cc +++ b/src/common/buffer.cc @@ -50,9 +50,9 @@ static ceph::spinlock debug_lock; # define bendl std::endl; } #endif - static std::atomic buffer_cached_crc { 0 }; - static std::atomic buffer_cached_crc_adjusted { 0 }; - static std::atomic buffer_missed_crc { 0 }; + static ceph::atomic buffer_cached_crc { 0 }; + static ceph::atomic buffer_cached_crc_adjusted { 0 }; + static ceph::atomic buffer_missed_crc { 0 }; static bool buffer_track_crc = get_env_bool("CEPH_BUFFER_TRACK"); diff --git a/src/common/ceph_atomic.h b/src/common/ceph_atomic.h new file mode 100644 index 00000000000..26a20ee2831 --- /dev/null +++ b/src/common/ceph_atomic.h @@ -0,0 +1,85 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#pragma once + +#include + +// What and why +// ============ +// +// ceph::atomic – thin wrapper to differentiate behavior of atomics. +// +// Not all users of the common truly need costly atomic operations to +// synchronize data between CPUs and threads. Some, like crimson-osd, +// stick to shared-nothing approach. Enforcing issue of atomics in +// such cases is wasteful – on x86 any locked instruction works actually +// like a full memory barrier stalling execution till CPU's store and +// load buffers are drained. + +#ifdef WITH_SEASTAR + +#include + +namespace ceph { + template + class dummy_atomic { + T value; + + public: + dummy_atomic() = default; + dummy_atomic(const dummy_atomic&) = delete; + dummy_atomic(T value) : value(std::move(value)) { + } + bool is_lock_free() const noexcept { + return true; + } + void store(T desired, std::memory_order) noexcept { + value = std::move(desired); + } + T load(std::memory_order = std::memory_order_seq_cst) const noexcept { + return value; + } + T operator=(T desired) noexcept { + value = std::move(desired); + } + operator T() const noexcept { + return value; + } + + // We need to differentiate with SFINAE as std::atomic offers beefier + // interface for integral types. + std::enable_if_t, T> operator++() { + return ++value; + } + std::enable_if_t, T> operator++(int) { + return value++; + } + std::enable_if_t, T> operator--() { + return --value; + } + std::enable_if_t, T> operator--(int) { + return value--; + } + std::enable_if_t, T> operator+=(const dummy_atomic& b) { + value += b; + return value; + } + std::enable_if_t, T> operator-=(const dummy_atomic& b) { + value -= b; + return value; + } + + static constexpr bool is_always_lock_free = true; + }; + + template using atomic = dummy_atomic; +} // namespace ceph + +#else // WITH_SEASTAR + +namespace ceph { + template using atomic = ::std::atomic; +} // namespace ceph + +#endif // WITH_SEASTAR diff --git a/src/crimson/CMakeLists.txt b/src/crimson/CMakeLists.txt index 25092fb84fe..3d2ffc066ef 100644 --- a/src/crimson/CMakeLists.txt +++ b/src/crimson/CMakeLists.txt @@ -18,6 +18,7 @@ add_library(crimson-common STATIC ${PROJECT_SOURCE_DIR}/src/common/admin_socket_client.cc ${PROJECT_SOURCE_DIR}/src/common/bit_str.cc ${PROJECT_SOURCE_DIR}/src/common/bloom_filter.cc + ${PROJECT_SOURCE_DIR}/src/common/buffer.cc ${PROJECT_SOURCE_DIR}/src/common/ceph_argparse.cc ${PROJECT_SOURCE_DIR}/src/common/ceph_context.cc ${PROJECT_SOURCE_DIR}/src/common/ceph_crypto.cc @@ -95,7 +96,6 @@ add_library(crimson-common STATIC ${PROJECT_SOURCE_DIR}/src/osd/PGPeeringEvent.cc ${crimson_common_srcs} $ - $ $ $) diff --git a/src/include/buffer_raw.h b/src/include/buffer_raw.h index a79afedbec5..a0483115782 100644 --- a/src/include/buffer_raw.h +++ b/src/include/buffer_raw.h @@ -15,10 +15,10 @@ #ifndef CEPH_BUFFER_RAW_H #define CEPH_BUFFER_RAW_H -#include #include #include #include +#include "common/ceph_atomic.h" #include "include/buffer.h" #include "include/mempool.h" #include "include/spinlock.h" @@ -34,7 +34,7 @@ inline namespace v14_2_0 { alignof(ptr_node)>::type bptr_storage; char *data; unsigned len; - std::atomic nref { 0 }; + ceph::atomic nref { 0 }; int mempool; std::pair last_crc_offset {std::numeric_limits::max(), std::numeric_limits::max()};