From 3c481423a1e64d4c43efa565b667f1e4e1fd5a61 Mon Sep 17 00:00:00 2001 From: Matt Millett Date: Fri, 21 Jun 2024 13:53:05 -0400 Subject: [PATCH] Enable mutex implementation and inlining strategy configurable at build-time --- cmake/templates/ntccfg_config.h | 15 ++ cmake/templates/ntscfg_config.h | 21 ++ configure | 66 +++++ configure.cmd | 68 +++++ groups/ntc/ntccfg/ntccfg_inline.h | 14 + groups/ntc/ntccfg/ntccfg_lock.h | 186 +------------ groups/ntc/ntccfg/ntccfg_mutex.cpp | 76 ++++++ groups/ntc/ntccfg/ntccfg_mutex.h | 377 +++++++++++++++++++++++++++ groups/ntc/ntccfg/ntccfg_mutex.t.cpp | 41 +++ groups/ntc/ntccfg/ntccfg_object.h | 18 +- groups/ntc/ntccfg/ntccfg_platform.h | 1 + groups/ntc/ntci/ntci_callback.t.cpp | 61 +++-- groups/ntc/ntci/ntci_mutex.cpp | 56 ---- groups/ntc/ntci/ntci_mutex.h | 138 +--------- groups/ntc/ntci/ntci_mutex.t.cpp | 38 --- groups/ntc/ntcq/ntcq_receive.t.cpp | 29 +-- groups/ntc/ntcs/ntcs_async.cpp | 20 +- groups/ntc/ntcs/ntcs_async.h | 16 +- groups/ntc/ntcs/ntcs_controller.cpp | 24 +- groups/ntc/ntcs/ntcs_controller.h | 8 +- groups/ntc/ntcs/ntcs_strand.cpp | 24 +- groups/ntc/ntcs/ntcs_strand.h | 8 +- groups/nts/ntscfg/ntscfg_platform.h | 14 + targets.cmake | 1 + variables.cmake | 154 +++++++++++ 25 files changed, 962 insertions(+), 512 deletions(-) create mode 100644 groups/ntc/ntccfg/ntccfg_mutex.cpp create mode 100644 groups/ntc/ntccfg/ntccfg_mutex.h create mode 100644 groups/ntc/ntccfg/ntccfg_mutex.t.cpp diff --git a/cmake/templates/ntccfg_config.h b/cmake/templates/ntccfg_config.h index 7442db3c..d44d7088 100644 --- a/cmake/templates/ntccfg_config.h +++ b/cmake/templates/ntccfg_config.h @@ -124,12 +124,27 @@ namespace ntccfg { // Build with metrics. #define NTC_BUILD_WITH_METRICS @NTF_BUILD_WITH_METRICS@ +// Build with inlining suggested. +#define NTC_BUILD_WITH_INLINING_SUGGESTED @NTF_BUILD_WITH_INLINING_SUGGESTED@ + +// Build with inlining forced. +#define NTC_BUILD_WITH_INLINING_FORCED @NTF_BUILD_WITH_INLINING_FORCED@ + +// Build with inlining disabled. +#define NTC_BUILD_WITH_INLINING_DISABLED @NTF_BUILD_WITH_INLINING_DISABLED@ + // Build with branch prediction. #define NTC_BUILD_WITH_BRANCH_PREDICTION @NTF_BUILD_WITH_BRANCH_PREDICTION@ // Build with mutually-exclusive locks implemented with spin locks. #define NTC_BUILD_WITH_SPIN_LOCKS @NTF_BUILD_WITH_SPIN_LOCKS@ +// Build with mutually-exclusive locks implemented with userspace mutexes. +#define NTC_BUILD_WITH_USERSPACE_MUTEXES @NTF_BUILD_WITH_USERSPACE_MUTEXES@ + +// Build with mutually-exclusive locks implemented with system mutexes. +#define NTC_BUILD_WITH_SYSTEM_MUTEXES @NTF_BUILD_WITH_SYSTEM_MUTEXES@ + // Build with mutually-exclusive locks implemented with recursive mutexes. #define NTC_BUILD_WITH_RECURSIVE_MUTEXES @NTF_BUILD_WITH_RECURSIVE_MUTEXES@ diff --git a/cmake/templates/ntscfg_config.h b/cmake/templates/ntscfg_config.h index 5ee9a642..edeecbf9 100644 --- a/cmake/templates/ntscfg_config.h +++ b/cmake/templates/ntscfg_config.h @@ -103,9 +103,30 @@ namespace ntscfg { // Build with metrics. #define NTS_BUILD_WITH_METRICS @NTF_BUILD_WITH_METRICS@ +// Build with inlining suggested. +#define NTS_BUILD_WITH_INLINING_SUGGESTED @NTF_BUILD_WITH_INLINING_SUGGESTED@ + +// Build with inlining forced. +#define NTS_BUILD_WITH_INLINING_FORCED @NTF_BUILD_WITH_INLINING_FORCED@ + +// Build with inlining disabled. +#define NTS_BUILD_WITH_INLINING_DISABLED @NTF_BUILD_WITH_INLINING_DISABLED@ + // Build with branch prediction. #define NTS_BUILD_WITH_BRANCH_PREDICTION @NTF_BUILD_WITH_BRANCH_PREDICTION@ +// Build with mutually-exclusive locks implemented with spin locks. +#define NTS_BUILD_WITH_SPIN_LOCKS @NTF_BUILD_WITH_SPIN_LOCKS@ + +// Build with mutually-exclusive locks implemented with userspace mutexes. +#define NTS_BUILD_WITH_USERSPACE_MUTEXES @NTF_BUILD_WITH_USERSPACE_MUTEXES@ + +// Build with mutually-exclusive locks implemented with system mutexes. +#define NTS_BUILD_WITH_SYSTEM_MUTEXES @NTF_BUILD_WITH_SYSTEM_MUTEXES@ + +// Build with mutually-exclusive locks implemented with recursive mutexes. +#define NTS_BUILD_WITH_RECURSIVE_MUTEXES @NTF_BUILD_WITH_RECURSIVE_MUTEXES@ + // Build with a test allocator that dumps stack traces upon memory leaks. #define NTS_BUILD_WITH_STACK_TRACE_TEST_ALLOCATOR @NTF_BUILD_WITH_STACK_TRACE_TEST_ALLOCATOR@ diff --git a/configure b/configure index fffdca30..d000e925 100755 --- a/configure +++ b/configure @@ -319,6 +319,18 @@ if [[ -z "${NTF_CONFIGURE_WITH_METRICS}" ]]; then NTF_CONFIGURE_WITH_METRICS=1 fi +if [[ -z "${NTF_CONFIGURE_WITH_INLINING_SUGGESTED}" ]]; then + NTF_CONFIGURE_WITH_INLINING_SUGGESTED=0 +fi + +if [[ -z "${NTF_CONFIGURE_WITH_INLINING_FORCED}" ]]; then + NTF_CONFIGURE_WITH_INLINING_FORCED=1 +fi + +if [[ -z "${NTF_CONFIGURE_WITH_INLINING_DISABLED}" ]]; then + NTF_CONFIGURE_WITH_INLINING_DISABLED=0 +fi + if [[ -z "${NTF_CONFIGURE_WITH_BRANCH_PREDICTION}" ]]; then NTF_CONFIGURE_WITH_BRANCH_PREDICTION=1 fi @@ -327,6 +339,22 @@ if [[ -z "${NTF_CONFIGURE_WITH_SPIN_LOCKS}" ]]; then NTF_CONFIGURE_WITH_SPIN_LOCKS=0 fi +if [[ -z "${NTF_CONFIGURE_WITH_USERSPACE_MUTEXES}" ]]; then + if [[ "${NTF_CONFIGURE_UNAME}" == "Linux" ]]; then + NTF_CONFIGURE_WITH_USERSPACE_MUTEXES=1 + else + NTF_CONFIGURE_WITH_USERSPACE_MUTEXES=0 + fi +fi + +if [[ -z "${NTF_CONFIGURE_WITH_SYSTEM_MUTEXES}" ]]; then + if [[ "${NTF_CONFIGURE_UNAME}" == "Linux" ]]; then + NTF_CONFIGURE_WITH_SYSTEM_MUTEXES=0 + else + NTF_CONFIGURE_WITH_SYSTEM_MUTEXES=1 + fi +fi + if [[ -z "${NTF_CONFIGURE_WITH_RECURSIVE_MUTEXES}" ]]; then NTF_CONFIGURE_WITH_RECURSIVE_MUTEXES=0 fi @@ -451,9 +479,16 @@ usage() echo " --with-logging Build with logging [${NTF_CONFIGURE_WITH_LOGGING}]" echo " --with-metrics Build with metrics [${NTF_CONFIGURE_WITH_METRICS}]" + + echo " --with-inlining-suggested Build functions suggested to be inlined by the compiler [${NTF_CONFIGURE_WITH_INLINING_SUGGESTED}]" + echo " --with-inlining-forced Build functions forcibly inlined [${NTF_CONFIGURE_WITH_INLINING_FORCED}]" + echo " --with-inlining-suggested Build with no functions inlined [${NTF_CONFIGURE_WITH_INLINING_DISABLED}]" + echo " --with-branch-prediction Build with branch prediction [${NTF_CONFIGURE_WITH_BRANCH_PREDICTION}]" echo " --with-spin-locks Build with mutually-exclusive locks implemented as spin locks [${NTF_CONFIGURE_WITH_SPIN_LOCKS}]" + echo " --with-userspace-mutexes Build with mutually-exclusive locks implemented as userspace mutexes [${NTF_CONFIGURE_WITH_USERSPACE_MUTEXES}]" + echo " --with-system-mutexes Build with mutually-exclusive locks implemented as system mutexes [${NTF_CONFIGURE_WITH_SYSTEM_MUTEXES}]" echo " --with-recursive-mutexes Build with mutually-exclusive locks implemented as recursive mutexes [${NTF_CONFIGURE_WITH_RECURSIVE_MUTEXES}]" echo " --with-stack-trace-leak-report Build chronology with stack traces dumped upon function and timer leaks [${NTF_CONFIGURE_WITH_STACK_TRACE_LEAK_REPORT}]" @@ -615,11 +650,23 @@ while true ; do NTF_CONFIGURE_WITH_LOGGING=1 ; shift ;; --with-metrics) NTF_CONFIGURE_WITH_METRICS=1 ; shift ;; + + --with-inlining-suggested) + NTF_CONFIGURE_WITH_INLINING_SUGGESTED=1 ; shift ;; + --with-inlining-forced) + NTF_CONFIGURE_WITH_INLINING_FORCED=1 ; shift ;; + --with-inlining-disabled) + NTF_CONFIGURE_WITH_INLINING_DISABLED=1 ; shift ;; + --with-branch-prediction) NTF_CONFIGURE_WITH_BRANCH_PREDICTION=1 ; shift ;; --with-spin-locks) NTF_CONFIGURE_WITH_SPIN_LOCKS=1 ; shift ;; + --with-userspace-mutexes) + NTF_CONFIGURE_WITH_USERSPACE_MUTEXES=1 ; shift ;; + --with-system-mutexes) + NTF_CONFIGURE_WITH_SYSTEM_MUTEXES=1 ; shift ;; --with-recursive-mutexes) NTF_CONFIGURE_WITH_RECURSIVE_MUTEXES=1 ; shift ;; @@ -710,11 +757,23 @@ while true ; do NTF_CONFIGURE_WITH_LOGGING=0 ; shift ;; --without-metrics) NTF_CONFIGURE_WITH_METRICS=0 ; shift ;; + + --without-inlining-suggested) + NTF_CONFIGURE_WITH_INLINING_SUGGESTED=0 ; shift ;; + --without-inlining-forced) + NTF_CONFIGURE_WITH_INLINING_FORCED=0 ; shift ;; + --without-inlining-disabled) + NTF_CONFIGURE_WITH_INLINING_DISABLED=0 ; shift ;; + --without-branch-prediction) NTF_CONFIGURE_WITH_BRANCH_PREDICTION=0 ; shift ;; --without-spin-locks) NTF_CONFIGURE_WITH_SPIN_LOCKS=0 ; shift ;; + --without-userspace-mutexes) + NTF_CONFIGURE_WITH_USERSPACE_MUTEXES=0 ; shift ;; + --without-system-mutexes) + NTF_CONFIGURE_WITH_SYSTEM_MUTEXES=0 ; shift ;; --without-recursive-mutexes) NTF_CONFIGURE_WITH_RECURSIVE_MUTEXES=0 ; shift ;; @@ -816,9 +875,16 @@ export NTF_CONFIGURE_WITH_DEPRECATED_FEATURES export NTF_CONFIGURE_WITH_LOGGING export NTF_CONFIGURE_WITH_METRICS + +export NTF_CONFIGURE_WITH_INLINING_SUGGESTED +export NTF_CONFIGURE_WITH_INLINING_FORCED +export NTF_CONFIGURE_WITH_INLINING_DISABLED + export NTF_CONFIGURE_WITH_BRANCH_PREDICTION export NTF_CONFIGURE_WITH_SPIN_LOCKS +export NTF_CONFIGURE_WITH_USERSPACE_MUTEXES +export NTF_CONFIGURE_WITH_SYSTEM_MUTEXES export NTF_CONFIGURE_WITH_RECURSIVE_MUTEXES export NTF_CONFIGURE_WITH_STACK_TRACE_LEAK_REPORT diff --git a/configure.cmd b/configure.cmd index 22f72659..f1088fa6 100644 --- a/configure.cmd +++ b/configure.cmd @@ -125,6 +125,18 @@ IF NOT DEFINED NTF_CONFIGURE_WITH_METRICS ( set NTF_CONFIGURE_WITH_METRICS=1 ) +IF NOT DEFINED NTF_CONFIGURE_WITH_INLINING_SUGGESTED ( + set NTF_CONFIGURE_WITH_INLINING_SUGGESTED=0 +) + +IF NOT DEFINED NTF_CONFIGURE_WITH_INLINING_FORCED ( + set NTF_CONFIGURE_WITH_INLINING_FORCED=1 +) + +IF NOT DEFINED NTF_CONFIGURE_WITH_INLINING_DISABLED ( + set NTF_CONFIGURE_WITH_INLINING_DISABLED=0 +) + IF NOT DEFINED NTF_CONFIGURE_WITH_BRANCH_PREDICTION ( set NTF_CONFIGURE_WITH_BRANCH_PREDICTION=1 ) @@ -133,6 +145,14 @@ IF NOT DEFINED NTF_CONFIGURE_WITH_SPIN_LOCKS ( set NTF_CONFIGURE_WITH_SPIN_LOCKS=0 ) +IF NOT DEFINED NTF_CONFIGURE_WITH_USERSPACE_MUTEXES ( + set NTF_CONFIGURE_WITH_USERSPACE_MUTEXES=0 +) + +IF NOT DEFINED NTF_CONFIGURE_WITH_SYSTEM_MUTEXES ( + set NTF_CONFIGURE_WITH_SYSTEM_MUTEXES=0 +) + IF NOT DEFINED NTF_CONFIGURE_WITH_RECURSIVE_MUTEXES ( set NTF_CONFIGURE_WITH_RECURSIVE_MUTEXES=0 ) @@ -290,10 +310,34 @@ if not "%1"=="" ( if "%1"=="--with-metrics" ( set NTF_CONFIGURE_WITH_METRICS=1 ) + + if "%1"=="--with-inlining-suggested" ( + set NTF_CONFIGURE_WITH_INLINING_SUGGESTED=1 + ) + if "%1"=="--with-inlining-forced" ( + set NTF_CONFIGURE_WITH_INLINING_FORCED=1 + ) + if "%1"=="--with-inlining-disabled" ( + set NTF_CONFIGURE_WITH_INLINING_DISABLED=1 + ) + if "%1"=="--with-branch-prediction" ( set NTF_CONFIGURE_WITH_BRANCH_PREDICTION=1 ) + if "%1"=="--with-spin-locks" ( + set NTF_CONFIGURE_WITH_SPIN_LOCKS=1 + ) + if "%1"=="--with-userspace-mutexes" ( + set NTF_CONFIGURE_WITH_USERSPACE_MUTEXES=1 + ) + if "%1"=="--with-system-mutexes" ( + set NTF_CONFIGURE_WITH_SYSTEM_MUTEXES=1 + ) + if "%1"=="--with-recursive-mutexes" ( + set NTF_CONFIGURE_WITH_RECURSIVE_MUTEXES=1 + ) + if "%1"=="--with-usage-examples" ( set NTF_CONFIGURE_WITH_USAGE_EXAMPLES=1 ) @@ -382,10 +426,34 @@ if not "%1"=="" ( if "%1"=="--without-metrics" ( set NTF_CONFIGURE_WITH_METRICS=0 ) + + if "%1"=="--without-inlining-suggested" ( + set NTF_CONFIGURE_WITH_INLINING_SUGGESTED=0 + ) + if "%1"=="--without-inlining-forced" ( + set NTF_CONFIGURE_WITH_INLINING_FORCED=0 + ) + if "%1"=="--without-inlining-disabled" ( + set NTF_CONFIGURE_WITH_INLINING_DISABLED=0 + ) + if "%1"=="--without-branch-prediction" ( set NTF_CONFIGURE_WITH_BRANCH_PREDICTION=0 ) + if "%1"=="--without-spin-locks" ( + set NTF_CONFIGURE_WITH_SPIN_LOCKS=0 + ) + if "%1"=="--without-userspace-mutexes" ( + set NTF_CONFIGURE_WITH_USERSPACE_MUTEXES=0 + ) + if "%1"=="--without-system-mutexes" ( + set NTF_CONFIGURE_WITH_SYSTEM_MUTEXES=0 + ) + if "%1"=="--without-recursive-mutexes" ( + set NTF_CONFIGURE_WITH_RECURSIVE_MUTEXES=0 + ) + if "%1"=="--without-usage-examples" ( set NTF_CONFIGURE_WITH_USAGE_EXAMPLES=0 ) diff --git a/groups/ntc/ntccfg/ntccfg_inline.h b/groups/ntc/ntccfg/ntccfg_inline.h index 1b61447c..3de4c9ae 100644 --- a/groups/ntc/ntccfg/ntccfg_inline.h +++ b/groups/ntc/ntccfg/ntccfg_inline.h @@ -23,6 +23,8 @@ BSLS_IDENT("$Id: $") #include #include +#if NTC_BUILD_WITH_INLINING_FORCED + #if defined(NDEBUG) || defined(BDE_BUILD_TARGET_OPT) #if defined(BSLS_PLATFORM_CMP_GNU) || defined(BSLS_PLATFORM_CMP_CLANG) @@ -51,4 +53,16 @@ BSLS_IDENT("$Id: $") #endif +#elif NTC_BUILD_WITH_INLINING_SUGGESTED + +/// Hint that the following function can be inlined at its call site. +/// @ingroup module_ntccfg +#define NTCCFG_INLINE inline + +#elif NTC_BUILD_WITH_INLINING_DISABLED +#error Not implemented +#else +#error Not implemented +#endif + #endif diff --git a/groups/ntc/ntccfg/ntccfg_lock.h b/groups/ntc/ntccfg/ntccfg_lock.h index 9492abbc..5c3a2c87 100644 --- a/groups/ntc/ntccfg/ntccfg_lock.h +++ b/groups/ntc/ntccfg/ntccfg_lock.h @@ -20,6 +20,7 @@ BSLS_IDENT("$Id: $") #include +#include #include #include #include @@ -44,206 +45,33 @@ namespace ntccfg { #define NTCCFG_LOCK_SCOPE_NAME(prefix, disambiguator) \ NTCCFG_LOCK_SCOPE_NAME_JOIN(prefix, disambiguator) -/// @internal @brief -/// Define a type alias for a spin lock. -/// -/// @ingroup module_ntccfg -typedef bsls::SpinLock SpinLock; - -/// @internal @brief -/// The initializer for a spin lock. -/// -/// @ingroup module_ntccfg -#define NTCCFG_LOCK_INIT_SPIN bsls::SpinLock::s_unlocked - -/// @internal @brief -/// Enter a stack scope, lock the specified spin-lock 'mutex' pointer, and -/// automatically unlock the 'mutex' when the stack scope is left. -/// -/// @ingroup module_ntccfg -#define NTCCFG_LOCK_SCOPE_ENTER_SPIN(mutex) \ - { \ - bsls::SpinLockGuard NTCCFG_LOCK_SCOPE_NAME(SPIN_LOCK_SCOPE_GUARD_, \ - __LINE__)((mutex)); \ - { -/// @internal @brief -/// Leave the current stack scope locked by the specified spin-lock 'mutex'. -/// -/// @ingroup module_ntccfg -#define NTCCFG_LOCK_SCOPE_LEAVE_SPIN(mutex) \ - } \ - } - -/// @internal @brief -/// Define a type alias for a basic, non-recursive mutex. -/// -/// @ingroup module_ntccfg -typedef bslmt::Mutex BasicMutex; - /// @internal @brief /// The initializer for a basic, non-recursive mutex. /// /// @ingroup module_ntccfg -#define NTCCFG_LOCK_INIT_BASIC +#define NTCCFG_LOCK_INIT /// @internal @brief /// Enter a stack scope, lock the specified basic, non-recursive 'mutex' /// pointer, and automatically unlock the 'mutex' when the stack scope is left. /// /// @ingroup module_ntccfg -#define NTCCFG_LOCK_SCOPE_ENTER_BASIC(mutex) \ +#define NTCCFG_LOCK_SCOPE_ENTER(mutex) \ { \ - bslmt::LockGuard NTCCFG_LOCK_SCOPE_NAME( \ - BASIC_MUTEX_SCOPE_GUARD_, \ + bslmt::LockGuard NTCCFG_LOCK_SCOPE_NAME( \ + LOCK_SCOPE_GUARD_, \ __LINE__)((mutex)); \ { + /// @internal @brief /// Leave the current stack scope locked by the specified basic, non-recursive /// 'mutex'. /// /// @ingroup module_ntccfg -#define NTCCFG_LOCK_SCOPE_LEAVE_BASIC(mutex) \ +#define NTCCFG_LOCK_SCOPE_LEAVE(mutex) \ } \ } -/// @internal @brief -/// Define a type alias for a recursive mutex. -/// -/// @ingroup module_ntccfg -typedef bslmt::RecursiveMutex RecursiveMutex; - -/// @internal @brief -/// The initializer for a recursive mutex. -/// -/// @ingroup module_ntccfg -#define NTCCFG_LOCK_INIT_RECURSIVE - -/// @internal @brief -/// Enter a stack scope, lock the specified recursive 'mutex' pointer, and -/// automatically unlock the 'mutex' when the stack scope is left. -/// -/// @ingroup module_ntccfg -#define NTCCFG_LOCK_SCOPE_ENTER_RECURSIVE(mutex) \ - { \ - bslmt::LockGuard NTCCFG_LOCK_SCOPE_NAME( \ - RECURSIVE_MUTEX_SCOPE_GUARD_, \ - __LINE__)((mutex)); \ - { -/// @internal @brief -/// Leave the current stack scope locked by the specified recursive 'mutex'. -/// -/// @ingroup module_ntccfg -#define NTCCFG_LOCK_SCOPE_LEAVE_RECURSIVE(mutex) \ - } \ - } - -#if NTC_BUILD_WITH_SPIN_LOCKS - -/// @internal @brief -/// Define a type alias for a non-recursive mutex, which may be -/// either a regular system mutex, a recursive mutex, or a spin lock, depending -/// on the build configuration. -/// -/// @ingroup module_ntccfg -typedef ntccfg::SpinLock Mutex; - -/// @internal @brief -/// The initializer for a non-recursive mutex, which may be either a regular -/// system mutex, a recursive mutex, or a spin lock, depending on the build -/// configuration. -/// -/// @ingroup module_ntccfg -#define NTCCFG_LOCK_INIT NTCCFG_LOCK_INIT_SPIN - -/// @internal @brief -/// Enter a stack scope, lock the specified 'mutex' pointer, which may be -/// either a regular system mutex, a recursive mutex, or a spin lock, depending -/// on the build configuration, and automatically unlock the 'mutex' when the -/// stack scope is left. -/// -/// @ingroup module_ntccfg -#define NTCCFG_LOCK_SCOPE_ENTER(mutex) NTCCFG_LOCK_SCOPE_ENTER_SPIN(mutex) - -/// @internal @brief -/// Leave the current stack scope locked by the specified 'mutex' pointer, -/// which may be either a regular system mutex, a recursive mutex, or a spin -/// lock, depending on the build configuration. -/// -/// @ingroup module_ntccfg -#define NTCCFG_LOCK_SCOPE_LEAVE(mutex) NTCCFG_LOCK_SCOPE_LEAVE_SPIN(mutex) - -#elif NTC_BUILD_WITH_RECURSIVE_MUTEXES - -/// @internal @brief -/// Define a type alias for a non-recursive mutex, which may be -/// either a regular system mutex, a recursive mutex, or a spin lock, depending -/// on the build configuration. -/// -/// @ingroup module_ntccfg -typedef ntccfg::RecursiveMutex Mutex; - -/// @internal @brief -/// The initializer for a non-recursive mutex, which may be either a regular -/// system mutex, a recursive mutex, or a spin lock, depending on the build -/// configuration. -/// -/// @ingroup module_ntccfg -#define NTCCFG_LOCK_INIT NTCCFG_LOCK_INIT_RECURSIVE - -/// @internal @brief -/// Enter a stack scope, lock the specified 'mutex' pointer, which may be -/// either a regular system mutex, a recursive mutex, or a spin lock, depending -/// on the build configuration, and automatically unlock the 'mutex' when the -/// stack scope is left. -/// -/// @ingroup module_ntccfg -#define NTCCFG_LOCK_SCOPE_ENTER(mutex) NTCCFG_LOCK_SCOPE_ENTER_RECURSIVE(mutex) - -/// @internal @brief -/// Leave the current stack scope locked by the specified 'mutex' pointer, -/// which may be either a regular system mutex, a recursive mutex, or a spin -/// lock, depending on the build configuration. -/// -/// @ingroup module_ntccfg -#define NTCCFG_LOCK_SCOPE_LEAVE(mutex) NTCCFG_LOCK_SCOPE_LEAVE_RECURSIVE(mutex) - -#else - -/// @internal @brief -/// Define a type alias for a non-recursive mutex, which may be -/// either a regular system mutex, a recursive mutex, or a spin lock, depending -/// on the build configuration. -/// -/// @ingroup module_ntccfg -typedef ntccfg::BasicMutex Mutex; - -/// @internal @brief -/// The initializer for a non-recursive mutex, which may be either a regular -/// system mutex, a recursive mutex, or a spin lock, depending on the build -/// configuration. -/// -/// @ingroup module_ntccfg -#define NTCCFG_LOCK_INIT NTCCFG_LOCK_INIT_BASIC - -/// @internal @brief -/// Enter a stack scope, lock the specified 'mutex' pointer, which may be -/// either a regular system mutex, a recursive mutex, or a spin lock, depending -/// on the build configuration, and automatically unlock the 'mutex' when the -/// stack scope is left. -/// -/// @ingroup module_ntccfg -#define NTCCFG_LOCK_SCOPE_ENTER(mutex) NTCCFG_LOCK_SCOPE_ENTER_BASIC(mutex) - -/// @internal @brief -/// Leave the current stack scope locked by the specified 'mutex' pointer, -/// which may be either a regular system mutex, a recursive mutex, or a spin -/// lock, depending on the build configuration. -/// -/// @ingroup module_ntccfg -#define NTCCFG_LOCK_SCOPE_LEAVE(mutex) NTCCFG_LOCK_SCOPE_LEAVE_BASIC(mutex) - -#endif - } // close package namespace } // close enterprise namespace #endif diff --git a/groups/ntc/ntccfg/ntccfg_mutex.cpp b/groups/ntc/ntccfg/ntccfg_mutex.cpp new file mode 100644 index 00000000..f63113e3 --- /dev/null +++ b/groups/ntc/ntccfg/ntccfg_mutex.cpp @@ -0,0 +1,76 @@ +// Copyright 2020-2023 Bloomberg Finance L.P. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include +BSLS_IDENT_RCSID(ntccfg_mutex_cpp, "$Id$ $CSID$") + +#include +#include +#include + +#if defined(BSLS_PLATFORM_OS_LINUX) +#include +#include +#include +#include +#endif + +namespace BloombergLP { +namespace ntccfg { + +#if NTCCFG_FUTEX_ENABLED + +// Some versions of GCC issue a spurious warning that the 'current' paramter +// is set but not used when 'Mutex::compareAndSwap' is called. +#if defined(BSLS_PLATFORM_CMP_GNU) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-but-set-parameter" +#endif + +__attribute__((noinline)) void Futex::wait() +{ + syscall(SYS_futex, (int*)(&d_value), FUTEX_WAIT, 2, 0, 0, 0); +} + +__attribute__((noinline)) void Futex::wake() +{ + syscall(SYS_futex, (int*)(&d_value), FUTEX_WAKE, 1, 0, 0, 0); +} + +__attribute__((noinline)) void Mutex::lockContention(int c) +{ + do { + if (c == 2 || compareAndSwap(&d_value, 1, 2) != 0) { + this->wait(); + } + } while ((c = compareAndSwap(&d_value, 0, 2)) != 0); +} + +__attribute__((noinline)) void Futex::unlockContention() +{ + __atomic_store_n(&d_value, 0, __ATOMIC_SEQ_CST); + this->wake(); +} + +#if defined(BSLS_PLATFORM_CMP_GNU) +#pragma GCC diagnostic pop +#endif + +#endif // NTCCFG_FUTEX_ENABLED + +} // close package namespace +} // close enterprise namespace diff --git a/groups/ntc/ntccfg/ntccfg_mutex.h b/groups/ntc/ntccfg/ntccfg_mutex.h new file mode 100644 index 00000000..86d3b7c9 --- /dev/null +++ b/groups/ntc/ntccfg/ntccfg_mutex.h @@ -0,0 +1,377 @@ +// Copyright 2020-2023 Bloomberg Finance L.P. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef INCLUDED_NTCCFG_MUTEX +#define INCLUDED_NTCCFG_MUTEX + +#include +BSLS_IDENT("$Id: $") + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(BSLS_PLATFORM_OS_LINUX) && \ + (defined(BSLS_PLATFORM_CMP_GNU) || defined(BSLS_PLATFORM_CMP_CLANG)) +#define NTCCFG_FUTEX_ENABLED 1 +#else +#define NTCCFG_FUTEX_ENABLED 0 +#endif + +namespace BloombergLP { +namespace ntccfg { + +#if NTCCFG_FUTEX_ENABLED + +// Some versions of GCC issue a spurious warning that the 'current' paramter +// is set but not used when 'Mutex::compareAndSwap' is called. +#if defined(BSLS_PLATFORM_CMP_GNU) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-but-set-parameter" +#endif + +/// @internal @brief +/// Provide a synchronization primitive for mutually-exclusive access +/// implemented by a Linux futex. +/// +/// @par Thread Safety +/// This class is thread safe. +/// +/// @ingroup module_ntccfg +class __attribute__((__aligned__(sizeof(int)))) Futex +{ + int d_value; + + private: + Futex(const Futex&) BSLS_KEYWORD_DELETED; + Futex& operator=(const Futex&) BSLS_KEYWORD_DELETED; + + private: + /// Wait until the lock may be acquired. + void wait(); + + /// Wake the next thread waiting to acquire the lock. + void wake(); + + /// Continue locking the mutex after discovering the mutex was probably + /// previously unlocked. + void lockContention(int c); + + /// Continue unlocking the mutex after discovering the mutex probably + /// has other threads trying to lock the mutex. + void unlockContention(); + + /// Compare the specified '*current' value to the specified 'expected' + /// value, and if equal, set '*current' to 'desired'. Return the + /// previous value of 'current'. + static int compareAndSwap(int* current, int expected, int desired); + + public: + /// Create a new mutex. + Futex(); + + /// Destroy this object. + ~Futex(); + + /// Lock the mutex. + void lock(); + + /// Unlock the mutex. + void unlock(); +}; + +NTCCFG_INLINE +int Mutex::compareAndSwap(int* current, int expected, int desired) +{ + int* ep = &expected; + int* dp = &desired; + + __atomic_compare_exchange(current, + ep, + dp, + false, + __ATOMIC_SEQ_CST, + __ATOMIC_SEQ_CST); + + return *ep; +} + +NTCCFG_INLINE +Mutex::Mutex() +{ + __atomic_store_n(&d_value, 0, __ATOMIC_RELAXED); +} + +NTCCFG_INLINE +Mutex::~Mutex() +{ +} + +NTCCFG_INLINE +void Mutex::lock() +{ + int previous = compareAndSwap(&d_value, 0, 1); + if (previous != 0) { + this->lockContention(previous); + } +} + +NTCCFG_INLINE +void Mutex::unlock() +{ + int previous = __atomic_fetch_sub(&d_value, 1, __ATOMIC_SEQ_CST); + if (previous != 1) { + this->unlockContention(); + } +} + +#if defined(BSLS_PLATFORM_CMP_GNU) +#pragma GCC diagnostic pop +#endif + +#endif // NTCCFG_FUTEX_ENABLED + +/// @internal @brief +/// Provide a synchronization primitive for mutually-exclusive access +/// implemented by a Linux futex. +/// +/// @par Thread Safety +/// This class is thread safe. +/// +/// @ingroup module_ntccfg +class SpinLock +{ + bsls::SpinLock d_lock; + + private: + SpinLock(const SpinLock&) BSLS_KEYWORD_DELETED; + SpinLock& operator=(const SpinLock&) BSLS_KEYWORD_DELETED; + + public: + /// Create a new spin lock. + SpinLock(); + + explicit SpinLock(int state); + + /// Destroy this object. + ~SpinLock(); + + /// Lock the mutex. + void lock(); + + /// Unlock the mutex. + void unlock(); +}; + +NTCCFG_INLINE +SpinLock::SpinLock() +: d_lock(bsls::SpinLock::s_unlocked) +{ +} + +NTCCFG_INLINE +SpinLock::~SpinLock() +{ +} + +NTCCFG_INLINE +void SpinLock::lock() +{ + d_lock.lock(); +} + +NTCCFG_INLINE +void SpinLock::unlock() +{ + d_lock.unlock(); +} + +/// @internal @brief +/// Implement mutexes by the mutex provided by BDE. +/// +/// @ingroup module_ntccfg +#define NTCCFG_MUTEX_IMPL_BSLMT_MUTEX 0 + +/// @internal @brief +/// Implement mutexes by the recursive mutex provided by BDE. +/// +/// @ingroup module_ntccfg +#define NTCCFG_MUTEX_IMPL_BSLMT_RECURSIVE_MUTEX 1 + +/// @internal @brief +/// Implement mutexes by a spin lock provided by BDE. +/// +/// @ingroup module_ntccfg +#define NTCCFG_MUTEX_IMPL_BSLMT_SPIN_LOCK 2 + +/// @internal @brief +/// Implement mutexes by a Linux futex. +/// +/// @ingroup module_ntccfg +#define NTCCFG_MUTEX_IMPL_FUTEX 3 + +#if NTC_BUILD_WITH_SPIN_LOCKS + +/// @internal @brief +/// The mutex implementation selector. +/// +/// @ingroup module_ntccfg +#define NTCCFG_MUTEX_IMPL NTCCFG_MUTEX_IMPL_BSLMT_SPIN_LOCK + +#elif NTC_BUILD_WITH_USERSPACE_MUTEXES + +#if NTCCFG_FUTEX_ENABLED + +/// @internal @brief +/// The mutex implementation selector. +/// +/// @ingroup module_ntccfg +#define NTCCFG_MUTEX_IMPL NTCCFG_MUTEX_IMPL_FUTEX + +#else + +/// @internal @brief +/// The mutex implementation selector. +/// +/// @ingroup module_ntccfg +#define NTCCFG_MUTEX_IMPL NTCCFG_MUTEX_IMPL_BSLMT_MUTEX + +#endif + +#elif NTC_BUILD_WITH_SYSTEM_MUTEXES + +/// @internal @brief +/// The mutex implementation selector. +/// +/// @ingroup module_ntccfg +#define NTCCFG_MUTEX_IMPL NTCCFG_MUTEX_IMPL_BSLMT_MUTEX + +#elif NTC_BUILD_WITH_RECURSIVE_MUTEXES + +/// @internal @brief +/// The mutex implementation selector. +/// +/// @ingroup module_ntccfg +#define NTCCFG_MUTEX_IMPL NTCCFG_MUTEX_IMPL_BSLMT_RECURSIVE_MUTEX + +#else +#error Not implemented +#endif + +#if NTCCFG_MUTEX_IMPL == NTCCFG_MUTEX_IMPL_BSLMT_MUTEX + +/// @internal @brief +/// Provide a synchronization primitive for mutually-exclusive access. +/// +/// @par Thread Safety +/// This class is thread safe. +/// +/// @ingroup module_ntccfg +typedef bslmt::Mutex Mutex; + +/// @internal @brief +/// Define a type alias for a guard to lock and unlock a mutex. +/// +/// @ingroup module_ntccfg +typedef bslmt::LockGuard LockGuard; + +/// @internal @brief +/// Define a type alias for a guard to unlock and lock a mutex. +/// +/// @ingroup module_ntccfg +typedef bslmt::UnLockGuard UnLockGuard; + +#elif NTCCFG_MUTEX_IMPL == NTCCFG_MUTEX_IMPL_BSLMT_RECURSIVE_MUTEX + +/// @internal @brief +/// Provide a synchronization primitive for mutually-exclusive access. +/// +/// @par Thread Safety +/// This class is thread safe. +/// +/// @ingroup module_ntccfg +typedef bslmt::RecursiveMutex Mutex; + +/// @internal @brief +/// Define a type alias for a guard to lock and unlock a mutex. +/// +/// @ingroup module_ntccfg +typedef bslmt::LockGuard LockGuard; + +/// @internal @brief +/// Define a type alias for a guard to unlock and lock a mutex. +/// +/// @ingroup module_ntccfg +typedef bslmt::UnLockGuard UnLockGuard; + +#elif NTCCFG_MUTEX_IMPL == NTCCFG_MUTEX_IMPL_BSLMT_SPIN_LOCK + +/// @internal @brief +/// Provide a synchronization primitive for mutually-exclusive access. +/// +/// @par Thread Safety +/// This class is thread safe. +/// +/// @ingroup module_ntccfg +typedef ntccfg::SpinLock Mutex; + +/// @internal @brief +/// Define a type alias for a guard to lock and unlock a mutex. +/// +/// @ingroup module_ntccfg +typedef bslmt::LockGuard LockGuard; + +/// @internal @brief +/// Define a type alias for a guard to unlock and lock a mutex. +/// +/// @ingroup module_ntccfg +typedef bslmt::UnLockGuard UnLockGuard; + +#elif NTCCFG_MUTEX_IMPL == NTCCFG_MUTEX_IMPL_BSLMT_FUTEX + +/// @internal @brief +/// Provide a synchronization primitive for mutually-exclusive access. +/// +/// @par Thread Safety +/// This class is thread safe. +/// +/// @ingroup module_ntccfg +typedef ntccfg::Futex Mutex; + +/// @internal @brief +/// Define a type alias for a guard to lock and unlock a mutex. +/// +/// @ingroup module_ntccfg +typedef bslmt::LockGuard LockGuard; + +/// @internal @brief +/// Define a type alias for a guard to unlock and lock a mutex. +/// +/// @ingroup module_ntccfg +typedef bslmt::UnLockGuard UnLockGuard; + +#else +#error Not implemented +#endif + +} // close package namespace +} // close enterprise namespace +#endif diff --git a/groups/ntc/ntccfg/ntccfg_mutex.t.cpp b/groups/ntc/ntccfg/ntccfg_mutex.t.cpp new file mode 100644 index 00000000..3d456979 --- /dev/null +++ b/groups/ntc/ntccfg/ntccfg_mutex.t.cpp @@ -0,0 +1,41 @@ +// Copyright 2020-2023 Bloomberg Finance L.P. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include + +#include +#include +#include + +using namespace BloombergLP; + +NTCCFG_TEST_CASE(1) +{ + ntccfg::Mutex mutex; + + mutex.lock(); + mutex.unlock(); + + mutex.lock(); + mutex.unlock(); +} + +NTCCFG_TEST_DRIVER +{ + NTCCFG_TEST_REGISTER(1); +} +NTCCFG_TEST_DRIVER_END; diff --git a/groups/ntc/ntccfg/ntccfg_object.h b/groups/ntc/ntccfg/ntccfg_object.h index a541810c..40d7bfa0 100644 --- a/groups/ntc/ntccfg/ntccfg_object.h +++ b/groups/ntc/ntccfg/ntccfg_object.h @@ -111,12 +111,26 @@ namespace ntccfg { d_lock.unlock(); \ } while (false) +/// @internal @brief +/// Concatenate two compile-type identifier into a single identifier. +/// +/// @ingroup module_ntccfg +#define NTCCFG_OBJECT_GUARD_NAME_JOIN(a, b) a##b + +/// @internal @brief +/// The identifier of a lock scope, formed from the specified 'prefix' +/// concatenated with the specified 'disambiguator'. +/// +/// @ingroup module_ntccfg +#define NTCCFG_OBJECT_GUARD_NAME(prefix, disambiguator) \ + NTCCFG_OBJECT_GUARD_NAME_JOIN(prefix, disambiguator) + /// @internal @brief /// Acquire a scoped strand execution lock. /// /// @ingroup module_ntccfg #define NTCCFG_OBJECT_GUARD(object) \ - ntccfg::ObjectGuard NTCCFG_LOCK_SCOPE_NAME( \ + ntccfg::ObjectGuard NTCCFG_OBJECT_GUARD_NAME( \ OBJECT_LOCK_SCOPE_GUARD_, \ __LINE__)((object), __FUNCTION__, __FILE__, __LINE__) @@ -127,6 +141,8 @@ namespace ntccfg { /// /// @par Thread Safety /// This class is thread safe. +/// +/// @ingroup module_ntccfg class Object { const char* d_typeName; diff --git a/groups/ntc/ntccfg/ntccfg_platform.h b/groups/ntc/ntccfg/ntccfg_platform.h index 11b86135..78b0f7ad 100644 --- a/groups/ntc/ntccfg/ntccfg_platform.h +++ b/groups/ntc/ntccfg/ntccfg_platform.h @@ -27,6 +27,7 @@ BSLS_IDENT("$Id: $") #include #include #include +#include #include #include #include diff --git a/groups/ntc/ntci/ntci_callback.t.cpp b/groups/ntc/ntci/ntci_callback.t.cpp index fe9af59b..934cbc49 100644 --- a/groups/ntc/ntci/ntci_callback.t.cpp +++ b/groups/ntc/ntci/ntci_callback.t.cpp @@ -110,14 +110,19 @@ class Authorization : public ntci::Authorization /// execution. class Executor : public ntci::Executor, public ntccfg::Shared { - /// Define a type alias for a queue of callbacks to - /// execute on this thread. + /// Define a type alias for a queue of callbacks to execute on this thread. typedef ntci::Executor::FunctorSequence FunctorQueue; - ntccfg::Object d_object; - mutable ntccfg::Mutex d_functorQueueMutex; - FunctorQueue d_functorQueue; - bslma::Allocator* d_allocator_p; + /// Define a type alias for a mutex. + typedef ntccfg::Mutex Mutex; + + /// Define a type alias for a mutex lock guard. + typedef ntccfg::LockGuard LockGuard; + + ntccfg::Object d_object; + mutable Mutex d_functorQueueMutex; + FunctorQueue d_functorQueue; + bslma::Allocator* d_allocator_p; private: Executor(const Executor&) BSLS_KEYWORD_DELETED; @@ -170,10 +175,16 @@ class Strand : public ntci::Strand, public ntccfg::Shared /// execute on this thread. typedef ntci::Executor::FunctorSequence FunctorQueue; - ntccfg::Object d_object; - mutable ntccfg::Mutex d_functorQueueMutex; - FunctorQueue d_functorQueue; - bslma::Allocator* d_allocator_p; + /// Define a type alias for a mutex. + typedef ntccfg::Mutex Mutex; + + /// Define a type alias for a mutex lock guard. + typedef ntccfg::LockGuard LockGuard; + + ntccfg::Object d_object; + mutable Mutex d_functorQueueMutex; + FunctorQueue d_functorQueue; + bslma::Allocator* d_allocator_p; private: Strand(const Strand&) BSLS_KEYWORD_DELETED; @@ -371,33 +382,28 @@ Executor::~Executor() void Executor::execute(const Functor& function) { - NTCCFG_LOCK_SCOPE_ENTER(&d_functorQueueMutex); + LockGuard lock(&d_functorQueueMutex); d_functorQueue.push_back(function); - - NTCCFG_LOCK_SCOPE_LEAVE(&d_functorQueueMutex); } void Executor::moveAndExecute(FunctorSequence* functorSequence, const Functor& functor) { - NTCCFG_LOCK_SCOPE_ENTER(&d_functorQueueMutex); + LockGuard lock(&d_functorQueueMutex); d_functorQueue.splice(d_functorQueue.end(), *functorSequence); if (functor) { d_functorQueue.push_back(functor); } - - NTCCFG_LOCK_SCOPE_LEAVE(&d_functorQueueMutex); } void Executor::drain() { FunctorQueue functorQueue; { - NTCCFG_LOCK_SCOPE_ENTER(&d_functorQueueMutex); + LockGuard lock(&d_functorQueueMutex); functorQueue.swap(d_functorQueue); - NTCCFG_LOCK_SCOPE_LEAVE(&d_functorQueueMutex); } for (FunctorQueue::iterator it = functorQueue.begin(); @@ -410,11 +416,9 @@ void Executor::drain() void Executor::clear() { - NTCCFG_LOCK_SCOPE_ENTER(&d_functorQueueMutex); + LockGuard lock(&d_functorQueueMutex); d_functorQueue.clear(); - - NTCCFG_LOCK_SCOPE_LEAVE(&d_functorQueueMutex); } bsl::shared_ptr Executor::create( @@ -443,33 +447,28 @@ Strand::~Strand() void Strand::execute(const Functor& function) { - NTCCFG_LOCK_SCOPE_ENTER(&d_functorQueueMutex); + LockGuard lock(&d_functorQueueMutex); d_functorQueue.push_back(function); - - NTCCFG_LOCK_SCOPE_LEAVE(&d_functorQueueMutex); } void Strand::moveAndExecute(FunctorSequence* functorSequence, const Functor& functor) { - NTCCFG_LOCK_SCOPE_ENTER(&d_functorQueueMutex); + LockGuard lock(&d_functorQueueMutex); d_functorQueue.splice(d_functorQueue.end(), *functorSequence); if (functor) { d_functorQueue.push_back(functor); } - - NTCCFG_LOCK_SCOPE_LEAVE(&d_functorQueueMutex); } void Strand::drain() { FunctorQueue functorQueue; { - NTCCFG_LOCK_SCOPE_ENTER(&d_functorQueueMutex); + LockGuard lock(&d_functorQueueMutex); functorQueue.swap(d_functorQueue); - NTCCFG_LOCK_SCOPE_LEAVE(&d_functorQueueMutex); } { @@ -486,11 +485,9 @@ void Strand::drain() void Strand::clear() { - NTCCFG_LOCK_SCOPE_ENTER(&d_functorQueueMutex); + LockGuard lock(&d_functorQueueMutex); d_functorQueue.clear(); - - NTCCFG_LOCK_SCOPE_LEAVE(&d_functorQueueMutex); } bool Strand::isRunningInCurrentThread() const diff --git a/groups/ntc/ntci/ntci_mutex.cpp b/groups/ntc/ntci/ntci_mutex.cpp index 98bab3c2..170513a1 100644 --- a/groups/ntc/ntci/ntci_mutex.cpp +++ b/groups/ntc/ntci/ntci_mutex.cpp @@ -18,59 +18,3 @@ #include BSLS_IDENT_RCSID(ntci_mutex_cpp, "$Id$ $CSID$") -#include -#include -#include - -#if defined(BSLS_PLATFORM_OS_LINUX) -#include -#include -#include -#include -#endif - -namespace BloombergLP { -namespace ntci { - -#if NTCI_MUTEX_SYSTEM - -// Some versions of GCC issue a spurious warning that the 'current' paramter -// is set but not used when 'Mutex::compareAndSwap' is called. -#if defined(BSLS_PLATFORM_CMP_GNU) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-but-set-parameter" -#endif - -__attribute__((noinline)) void Mutex::wait() -{ - syscall(SYS_futex, (int*)(&d_value), FUTEX_WAIT, 2, 0, 0, 0); -} - -__attribute__((noinline)) void Mutex::wake() -{ - syscall(SYS_futex, (int*)(&d_value), FUTEX_WAKE, 1, 0, 0, 0); -} - -__attribute__((noinline)) void Mutex::lockContention(int c) -{ - do { - if (c == 2 || compareAndSwap(&d_value, 1, 2) != 0) { - this->wait(); - } - } while ((c = compareAndSwap(&d_value, 0, 2)) != 0); -} - -__attribute__((noinline)) void Mutex::unlockContention() -{ - __atomic_store_n(&d_value, 0, __ATOMIC_SEQ_CST); - this->wake(); -} - -#if defined(BSLS_PLATFORM_CMP_GNU) -#pragma GCC diagnostic pop -#endif - -#endif - -} // close package namespace -} // close enterprise namespace diff --git a/groups/ntc/ntci/ntci_mutex.h b/groups/ntc/ntci/ntci_mutex.h index 330eda35..9241bd9d 100644 --- a/groups/ntc/ntci/ntci_mutex.h +++ b/groups/ntc/ntci/ntci_mutex.h @@ -20,160 +20,32 @@ BSLS_IDENT("$Id: $") #include +#include #include -#include -#include -#include -#include -#include - -#if defined(BSLS_PLATFORM_OS_LINUX) && \ - (defined(BSLS_PLATFORM_CMP_GNU) || defined(BSLS_PLATFORM_CMP_CLANG)) -#define NTCI_MUTEX_SYSTEM 1 -#else -#define NTCI_MUTEX_SYSTEM 0 -#endif namespace BloombergLP { namespace ntci { -#if NTCI_MUTEX_SYSTEM - -// Some versions of GCC issue a spurious warning that the 'current' paramter -// is set but not used when 'Mutex::compareAndSwap' is called. -#if defined(BSLS_PLATFORM_CMP_GNU) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-but-set-parameter" -#endif - /// @internal @brief /// Provide a synchronization primitive for mutually-exclusive access. /// /// @par Thread Safety -// This class is thread safe. +/// This class is thread safe. /// /// @ingroup module_ntci_utility -class __attribute__((__aligned__(sizeof(int)))) Mutex -{ - int d_value; - - private: - Mutex(const Mutex&) BSLS_KEYWORD_DELETED; - Mutex& operator=(const Mutex&) BSLS_KEYWORD_DELETED; - - private: - /// Wait until the lock may be acquired. - void wait(); - - /// Wake the next thread waiting to acquire the lock. - void wake(); - - /// Continue locking the mutex after discovering the mutex was probably - /// previously unlocked. - void lockContention(int c); - - /// Continue unlocking the mutex after discovering the mutex probably - /// has other threads trying to lock the mutex. - void unlockContention(); - - /// Compare the specified '*current' value to the specified 'expected' - /// value, and if equal, set '*current' to 'desired'. Return the - /// previous value of 'current'. - static int compareAndSwap(int* current, int expected, int desired); - - public: - /// Create a new mutex. - Mutex(); - - /// Destroy this object. - ~Mutex(); - - /// Lock the mutex. - void lock(); - - /// Unlock the mutex. - void unlock(); -}; +typedef ntccfg::Mutex Mutex; /// @internal @brief /// Define a type alias for a guard to lock and unlock a mutex. /// /// @ingroup module_ntci_utility -typedef bslmt::LockGuard LockGuard; +typedef ntccfg::LockGuard LockGuard; /// @internal @brief /// Define a type alias for a guard to unlock and lock a mutex. /// /// @ingroup module_ntci_utility -typedef bslmt::UnLockGuard UnLockGuard; - -NTCCFG_INLINE -int Mutex::compareAndSwap(int* current, int expected, int desired) -{ - int* ep = &expected; - int* dp = &desired; - - __atomic_compare_exchange(current, - ep, - dp, - false, - __ATOMIC_SEQ_CST, - __ATOMIC_SEQ_CST); - - return *ep; -} - -NTCCFG_INLINE -Mutex::Mutex() -{ - __atomic_store_n(&d_value, 0, __ATOMIC_RELAXED); -} - -NTCCFG_INLINE -Mutex::~Mutex() -{ -} - -NTCCFG_INLINE -void Mutex::lock() -{ - int previous = compareAndSwap(&d_value, 0, 1); - if (previous != 0) { - this->lockContention(previous); - } -} - -NTCCFG_INLINE -void Mutex::unlock() -{ - int previous = __atomic_fetch_sub(&d_value, 1, __ATOMIC_SEQ_CST); - if (previous != 1) { - this->unlockContention(); - } -} - -#if defined(BSLS_PLATFORM_CMP_GNU) -#pragma GCC diagnostic pop -#endif - -#else - -/// @internal @brief -/// Provide a synchronization primitive for mutually-exclusive access. -/// -/// @par Thread Safety -// This class is thread safe. -typedef bslmt::Mutex Mutex; - -/// @internal @brief -/// Define a type alias for a guard to lock and unlock a mutex. -typedef bslmt::LockGuard LockGuard; - -/// @internal @brief -/// Define a type alias for a guard to unlock and lock a mutex. -typedef bslmt::UnLockGuard UnLockGuard; - -#endif +typedef ntccfg::LockGuard UnLockGuard; } // close package namespace } // close enterprise namespace diff --git a/groups/ntc/ntci/ntci_mutex.t.cpp b/groups/ntc/ntci/ntci_mutex.t.cpp index 28dd366b..697690f5 100644 --- a/groups/ntc/ntci/ntci_mutex.t.cpp +++ b/groups/ntc/ntci/ntci_mutex.t.cpp @@ -17,48 +17,10 @@ #include -#include -#include -#include - using namespace BloombergLP; -//============================================================================= -// TEST PLAN -//----------------------------------------------------------------------------- -// Overview -// -------- -// -//----------------------------------------------------------------------------- - -// [ 1] -//----------------------------------------------------------------------------- -// [ 1] -//----------------------------------------------------------------------------- - NTCCFG_TEST_CASE(1) { - // Concern: - // Plan: - -#if 0 - { - int value = 1; - - int previous = ntci::Mutex::compareAndSwap(&value, 1, 2); - NTCCFG_TEST_EQ(previous, 1); - NTCCFG_TEST_EQ(value, 2); - } - - { - int value = 1; - - int previous = ntci::Mutex::compareAndSwap(&value, 3, 2); - NTCCFG_TEST_EQ(previous, 1); - NTCCFG_TEST_EQ(value, 1); - } -#endif - ntci::Mutex mutex; mutex.lock(); diff --git a/groups/ntc/ntcq/ntcq_receive.t.cpp b/groups/ntc/ntcq/ntcq_receive.t.cpp index cdfc66f5..ee2a0ec3 100644 --- a/groups/ntc/ntcq/ntcq_receive.t.cpp +++ b/groups/ntc/ntcq/ntcq_receive.t.cpp @@ -48,10 +48,16 @@ class Strand : public ntci::Strand, public ntccfg::Shared /// execute on this thread. typedef ntci::Executor::FunctorSequence FunctorQueue; - ntccfg::Object d_object; - mutable ntccfg::Mutex d_functorQueueMutex; - FunctorQueue d_functorQueue; - bslma::Allocator* d_allocator_p; + /// Define a type alias for a mutex. + typedef ntccfg::Mutex Mutex; + + /// Define a type alias for a mutex lock guard. + typedef ntccfg::LockGuard LockGuard; + + ntccfg::Object d_object; + mutable Mutex d_functorQueueMutex; + FunctorQueue d_functorQueue; + bslma::Allocator* d_allocator_p; private: Strand(const Strand&) BSLS_KEYWORD_DELETED; @@ -104,33 +110,28 @@ Strand::~Strand() void Strand::execute(const Functor& function) { - NTCCFG_LOCK_SCOPE_ENTER(&d_functorQueueMutex); + LockGuard lock(&d_functorQueueMutex); d_functorQueue.push_back(function); - - NTCCFG_LOCK_SCOPE_LEAVE(&d_functorQueueMutex); } void Strand::moveAndExecute(FunctorSequence* functorSequence, const Functor& functor) { - NTCCFG_LOCK_SCOPE_ENTER(&d_functorQueueMutex); + LockGuard lock(&d_functorQueueMutex); d_functorQueue.splice(d_functorQueue.end(), *functorSequence); if (functor) { d_functorQueue.push_back(functor); } - - NTCCFG_LOCK_SCOPE_LEAVE(&d_functorQueueMutex); } void Strand::drain() { FunctorQueue functorQueue; { - NTCCFG_LOCK_SCOPE_ENTER(&d_functorQueueMutex); + LockGuard lock(&d_functorQueueMutex); functorQueue.swap(d_functorQueue); - NTCCFG_LOCK_SCOPE_LEAVE(&d_functorQueueMutex); } for (FunctorQueue::iterator it = functorQueue.begin(); @@ -143,11 +144,9 @@ void Strand::drain() void Strand::clear() { - NTCCFG_LOCK_SCOPE_ENTER(&d_functorQueueMutex); + LockGuard lock(&d_functorQueueMutex); d_functorQueue.clear(); - - NTCCFG_LOCK_SCOPE_LEAVE(&d_functorQueueMutex); } void processData(bsls::AtomicUint* numInvoked, diff --git a/groups/ntc/ntcs/ntcs_async.cpp b/groups/ntc/ntcs/ntcs_async.cpp index a3612906..bb655b16 100644 --- a/groups/ntc/ntcs/ntcs_async.cpp +++ b/groups/ntc/ntcs/ntcs_async.cpp @@ -199,7 +199,7 @@ void AsyncStrand::invoke() while (true) { bdlb::NullableValue functorQueue(d_allocator_p); { - NTCCFG_LOCK_SCOPE_ENTER(&d_functorQueueMutex); + LockGuard lock(&d_functorQueueMutex); BSLS_ASSERT(d_pending); @@ -210,8 +210,6 @@ void AsyncStrand::invoke() d_pending = false; break; } - - NTCCFG_LOCK_SCOPE_LEAVE(&d_functorQueueMutex); } FunctorQueue::iterator it = functorQueue.value().begin(); @@ -246,7 +244,7 @@ void AsyncStrand::execute(const Functor& function) { bool activate = false; { - NTCCFG_LOCK_SCOPE_ENTER(&d_functorQueueMutex); + LockGuard lock(&d_functorQueueMutex); d_functorQueue.push_back(function); @@ -254,8 +252,6 @@ void AsyncStrand::execute(const Functor& function) d_pending = true; activate = true; } - - NTCCFG_LOCK_SCOPE_LEAVE(&d_functorQueueMutex); } if (activate) { @@ -269,7 +265,7 @@ void AsyncStrand::moveAndExecute(FunctorSequence* functorSequence, { bool activate = false; { - NTCCFG_LOCK_SCOPE_ENTER(&d_functorQueueMutex); + LockGuard lock(&d_functorQueueMutex); d_functorQueue.splice(d_functorQueue.end(), *functorSequence); if (functor) { @@ -280,8 +276,6 @@ void AsyncStrand::moveAndExecute(FunctorSequence* functorSequence, d_pending = true; activate = true; } - - NTCCFG_LOCK_SCOPE_LEAVE(&d_functorQueueMutex); } if (activate) { @@ -295,7 +289,7 @@ void AsyncStrand::drain() while (true) { bdlb::NullableValue functorQueue(d_allocator_p); { - NTCCFG_LOCK_SCOPE_ENTER(&d_functorQueueMutex); + LockGuard lock(&d_functorQueueMutex); BSLS_ASSERT(!d_pending); @@ -305,8 +299,6 @@ void AsyncStrand::drain() else { break; } - - NTCCFG_LOCK_SCOPE_LEAVE(&d_functorQueueMutex); } FunctorQueue::iterator it = functorQueue.value().begin(); @@ -325,11 +317,9 @@ void AsyncStrand::drain() void AsyncStrand::clear() { - NTCCFG_LOCK_SCOPE_ENTER(&d_functorQueueMutex); + LockGuard lock(&d_functorQueueMutex); d_functorQueue.clear(); - - NTCCFG_LOCK_SCOPE_LEAVE(&d_functorQueueMutex); } bool AsyncStrand::isRunningInCurrentThread() const diff --git a/groups/ntc/ntcs/ntcs_async.h b/groups/ntc/ntcs/ntcs_async.h index b695e993..98d4e650 100644 --- a/groups/ntc/ntcs/ntcs_async.h +++ b/groups/ntc/ntcs/ntcs_async.h @@ -121,11 +121,17 @@ class AsyncStrand : public ntci::Strand, public ntccfg::Shared /// execute on this thread. typedef ntci::Executor::FunctorSequence FunctorQueue; - ntccfg::Object d_object; - mutable ntccfg::Mutex d_functorQueueMutex; - FunctorQueue d_functorQueue; - bool d_pending; - bslma::Allocator* d_allocator_p; + /// Define a type alias for a mutex. + typedef ntccfg::Mutex Mutex; + + /// Define a type alias for a mutex lock guard. + typedef ntccfg::LockGuard LockGuard; + + ntccfg::Object d_object; + mutable Mutex d_functorQueueMutex; + FunctorQueue d_functorQueue; + bool d_pending; + bslma::Allocator* d_allocator_p; private: AsyncStrand(const AsyncStrand&) BSLS_KEYWORD_DELETED; diff --git a/groups/ntc/ntcs/ntcs_controller.cpp b/groups/ntc/ntcs/ntcs_controller.cpp index 7417bbe4..e8f0874d 100644 --- a/groups/ntc/ntcs/ntcs_controller.cpp +++ b/groups/ntc/ntcs/ntcs_controller.cpp @@ -440,7 +440,7 @@ ntsa::Error Controller::interrupt(unsigned int numWakeups) NTCI_LOG_CONTEXT(); - NTCCFG_LOCK_SCOPE_ENTER(&d_mutex); + LockGuard lock(&d_mutex); if (numWakeups <= d_pending) { return ntsa::Error(); @@ -481,15 +481,13 @@ ntsa::Error Controller::interrupt(unsigned int numWakeups) NTCS_CONTROLLER_LOG_ENQUEUE(numToWrite, d_pending); - NTCCFG_LOCK_SCOPE_LEAVE(&d_mutex); - return ntsa::Error(); #elif NTCS_CONTROLLER_IMP == NTCS_CONTROLLER_IMP_ANONYMOUS_PIPE NTCI_LOG_CONTEXT(); - NTCCFG_LOCK_SCOPE_ENTER(&d_mutex); + LockGuard lock(&d_mutex); if (numWakeups <= d_pending) { return ntsa::Error(); @@ -525,15 +523,13 @@ ntsa::Error Controller::interrupt(unsigned int numWakeups) NTCS_CONTROLLER_LOG_ENQUEUE(numToWrite, d_pending); - NTCCFG_LOCK_SCOPE_LEAVE(&d_mutex); - return ntsa::Error(); #elif NTCS_CONTROLLER_IMP == NTCS_CONTROLLER_IMP_EVENTFD NTCI_LOG_CONTEXT(); - NTCCFG_LOCK_SCOPE_ENTER(&d_mutex); + LockGuard lock(&d_mutex); if (numWakeups <= d_pending) { return ntsa::Error(); @@ -571,8 +567,6 @@ ntsa::Error Controller::interrupt(unsigned int numWakeups) NTCS_CONTROLLER_LOG_ENQUEUE(numToWrite, d_pending); } - NTCCFG_LOCK_SCOPE_LEAVE(&d_mutex); - return ntsa::Error(); #else @@ -587,7 +581,7 @@ ntsa::Error Controller::acknowledge() NTCI_LOG_CONTEXT(); - NTCCFG_LOCK_SCOPE_ENTER(&d_mutex); + LockGuard lock(&d_mutex); char buffer; @@ -613,15 +607,13 @@ ntsa::Error Controller::acknowledge() NTCS_CONTROLLER_LOG_DEQUEUE(context.bytesReceived(), d_pending); - NTCCFG_LOCK_SCOPE_LEAVE(&d_mutex); - return ntsa::Error(); #elif NTCS_CONTROLLER_IMP == NTCS_CONTROLLER_IMP_ANONYMOUS_PIPE NTCI_LOG_CONTEXT(); - NTCCFG_LOCK_SCOPE_ENTER(&d_mutex); + LockGuard lock(&d_mutex); char buffer; bsl::size_t bytesRead = 0; @@ -647,15 +639,13 @@ ntsa::Error Controller::acknowledge() NTCS_CONTROLLER_LOG_DEQUEUE(bytesRead, d_pending); - NTCCFG_LOCK_SCOPE_LEAVE(&d_mutex); - return ntsa::Error(); #elif NTCS_CONTROLLER_IMP == NTCS_CONTROLLER_IMP_EVENTFD NTCI_LOG_CONTEXT(); - NTCCFG_LOCK_SCOPE_ENTER(&d_mutex); + LockGuard lock(&d_mutex); bsl::uint64_t value = 0; @@ -681,8 +671,6 @@ ntsa::Error Controller::acknowledge() NTCS_CONTROLLER_LOG_DEQUEUE(value, d_pending); - NTCCFG_LOCK_SCOPE_LEAVE(&d_mutex); - return ntsa::Error(); #else diff --git a/groups/ntc/ntcs/ntcs_controller.h b/groups/ntc/ntcs/ntcs_controller.h index 334c4e27..4314ede6 100644 --- a/groups/ntc/ntcs/ntcs_controller.h +++ b/groups/ntc/ntcs/ntcs_controller.h @@ -59,7 +59,13 @@ class Controller : public ntci::ReactorSocket e_EVENT }; - ntccfg::Mutex d_mutex; + /// Define a type alias for a mutex. + typedef ntccfg::Mutex Mutex; + + /// Define a type alias for a mutex lock guard. + typedef ntccfg::LockGuard LockGuard; + + Mutex d_mutex; ntsa::Handle d_clientHandle; ntsa::Handle d_serverHandle; bsl::size_t d_pending; diff --git a/groups/ntc/ntcs/ntcs_strand.cpp b/groups/ntc/ntcs/ntcs_strand.cpp index 8e17fbd6..02673ace 100644 --- a/groups/ntc/ntcs/ntcs_strand.cpp +++ b/groups/ntc/ntcs/ntcs_strand.cpp @@ -110,7 +110,7 @@ void Strand::invoke() while (true) { bdlb::NullableValue functorQueue(d_allocator_p); { - NTCCFG_LOCK_SCOPE_ENTER(&d_functorQueueMutex); + LockGuard lock(&d_functorQueueMutex); BSLS_ASSERT(d_pending); @@ -123,8 +123,6 @@ void Strand::invoke() d_pending = false; break; } - - NTCCFG_LOCK_SCOPE_LEAVE(&d_functorQueueMutex); } NTCS_STRAND_LOG_EXECUTION_STARTING(this, functorQueue.value()); @@ -150,7 +148,7 @@ void Strand::invoke() bool activate = false; { - NTCCFG_LOCK_SCOPE_ENTER(&d_functorQueueMutex); + LockGuard lock(&d_functorQueueMutex); BSLS_ASSERT(d_pending); BSLS_ASSERT(!d_functorQueue.empty()); @@ -161,8 +159,6 @@ void Strand::invoke() activate = !d_functorQueue.empty(); d_pending = activate; - - NTCCFG_LOCK_SCOPE_LEAVE(&d_functorQueueMutex); } { @@ -208,7 +204,7 @@ void Strand::execute(const Functor& function) { bool activate = false; { - NTCCFG_LOCK_SCOPE_ENTER(&d_functorQueueMutex); + LockGuard lock(&d_functorQueueMutex); d_functorQueue.push_back(function); @@ -218,8 +214,6 @@ void Strand::execute(const Functor& function) d_pending = true; activate = true; } - - NTCCFG_LOCK_SCOPE_LEAVE(&d_functorQueueMutex); } if (activate) { @@ -242,7 +236,7 @@ void Strand::moveAndExecute(FunctorSequence* functorSequence, { bool activate = false; { - NTCCFG_LOCK_SCOPE_ENTER(&d_functorQueueMutex); + LockGuard lock(&d_functorQueueMutex); d_functorQueue.splice(d_functorQueue.end(), *functorSequence); if (functor) { @@ -253,8 +247,6 @@ void Strand::moveAndExecute(FunctorSequence* functorSequence, d_pending = true; activate = true; } - - NTCCFG_LOCK_SCOPE_LEAVE(&d_functorQueueMutex); } if (activate) { @@ -275,7 +267,7 @@ void Strand::drain() while (true) { bdlb::NullableValue functorQueue(d_allocator_p); { - NTCCFG_LOCK_SCOPE_ENTER(&d_functorQueueMutex); + LockGuard lock(&d_functorQueueMutex); BSLS_ASSERT(!d_pending); @@ -287,8 +279,6 @@ void Strand::drain() NTCS_STRAND_LOG_QUEUE_EMPTY(this); break; } - - NTCCFG_LOCK_SCOPE_LEAVE(&d_functorQueueMutex); } NTCS_STRAND_LOG_EXECUTION_STARTING(this, functorQueue.value()); @@ -311,11 +301,9 @@ void Strand::drain() void Strand::clear() { - NTCCFG_LOCK_SCOPE_ENTER(&d_functorQueueMutex); + LockGuard lock(&d_functorQueueMutex); d_functorQueue.clear(); - - NTCCFG_LOCK_SCOPE_LEAVE(&d_functorQueueMutex); } bool Strand::isRunningInCurrentThread() const diff --git a/groups/ntc/ntcs/ntcs_strand.h b/groups/ntc/ntcs/ntcs_strand.h index 9e1e1655..45e8c152 100644 --- a/groups/ntc/ntcs/ntcs_strand.h +++ b/groups/ntc/ntcs/ntcs_strand.h @@ -46,8 +46,14 @@ class Strand : public ntci::Strand, public ntccfg::Shared /// execute on this thread. typedef ntci::Executor::FunctorSequence FunctorQueue; + /// Define a type alias for a mutex. + typedef ntccfg::Mutex Mutex; + + /// Define a type alias for a mutex lock guard. + typedef ntccfg::LockGuard LockGuard; + ntccfg::Object d_object; - mutable ntccfg::Mutex d_functorQueueMutex; + mutable Mutex d_functorQueueMutex; FunctorQueue d_functorQueue; ntcs::Observer d_executor; bool d_pending; diff --git a/groups/nts/ntscfg/ntscfg_platform.h b/groups/nts/ntscfg/ntscfg_platform.h index ce9482d7..fbe88632 100644 --- a/groups/nts/ntscfg/ntscfg_platform.h +++ b/groups/nts/ntscfg/ntscfg_platform.h @@ -39,6 +39,8 @@ BSLS_IDENT("$Id: $") namespace BloombergLP { namespace ntscfg { +#if NTS_BUILD_WITH_INLINING_FORCED + #if defined(NDEBUG) || defined(BDE_BUILD_TARGET_OPT) #if defined(BSLS_PLATFORM_CMP_GNU) || defined(BSLS_PLATFORM_CMP_CLANG) @@ -67,6 +69,18 @@ namespace ntscfg { #endif +#elif NTS_BUILD_WITH_INLINING_SUGGESTED + +/// Hint that the following function can be inlined at its call site. +/// @ingroup module_ntccfg +#define NTSCFG_INLINE inline + +#elif NTS_BUILD_WITH_INLINING_DISABLED +#error Not implemented +#else +#error Not implemented +#endif + #if NTS_BUILD_WITH_BRANCH_PREDICTION /// @internal @brief diff --git a/targets.cmake b/targets.cmake index 3c979f86..ca05f1aa 100644 --- a/targets.cmake +++ b/targets.cmake @@ -351,6 +351,7 @@ if (${NTF_BUILD_WITH_NTC}) ntf_component(NAME ntccfg_likely) ntf_component(NAME ntccfg_limits) ntf_component(NAME ntccfg_lock) + ntf_component(NAME ntccfg_mutex) ntf_component(NAME ntccfg_object) ntf_component(NAME ntccfg_platform) ntf_component(NAME ntccfg_test) diff --git a/variables.cmake b/variables.cmake index 3ec56597..015401f2 100644 --- a/variables.cmake +++ b/variables.cmake @@ -608,6 +608,63 @@ if (NOT DEFINED NTF_BUILD_WITH_METRICS) endif() endif() +if (NOT DEFINED NTF_BUILD_WITH_INLINING_SUGGESTED) + if (DEFINED NTF_CONFIGURE_WITH_INLINING_SUGGESTED) + set(NTF_BUILD_WITH_INLINING_SUGGESTED + ${NTF_CONFIGURE_WITH_INLINING_SUGGESTED} CACHE INTERNAL "") + elseif (DEFINED ENV{NTF_CONFIGURE_WITH_INLINING_SUGGESTED}) + set(NTF_BUILD_WITH_INLINING_SUGGESTED + $ENV{NTF_CONFIGURE_WITH_INLINING_SUGGESTED} CACHE INTERNAL "") + else() + set(NTF_BUILD_WITH_INLINING_SUGGESTED FALSE CACHE INTERNAL "") + endif() +endif() + +if (NOT DEFINED NTF_BUILD_WITH_INLINING_FORCED) + if (DEFINED NTF_CONFIGURE_WITH_INLINING_FORCED) + set(NTF_BUILD_WITH_INLINING_FORCED + ${NTF_CONFIGURE_WITH_INLINING_FORCED} CACHE INTERNAL "") + elseif (DEFINED ENV{NTF_CONFIGURE_WITH_INLINING_FORCED}) + set(NTF_BUILD_WITH_INLINING_FORCED + $ENV{NTF_CONFIGURE_WITH_INLINING_FORCED} CACHE INTERNAL "") + else() + set(NTF_BUILD_WITH_INLINING_FORCED TRUE CACHE INTERNAL "") + endif() +endif() + +if (NOT DEFINED NTF_BUILD_WITH_INLINING_DISABLED) + if (DEFINED NTF_CONFIGURE_WITH_INLINING_DISABLED) + set(NTF_BUILD_WITH_INLINING_DISABLED + ${NTF_CONFIGURE_WITH_INLINING_DISABLED} CACHE INTERNAL "") + elseif (DEFINED ENV{NTF_CONFIGURE_WITH_INLINING_DISABLED}) + set(NTF_BUILD_WITH_INLINING_DISABLED + $ENV{NTF_CONFIGURE_WITH_INLINING_DISABLED} CACHE INTERNAL "") + else() + set(NTF_BUILD_WITH_INLINING_DISABLED FALSE CACHE INTERNAL "") + endif() +endif() + +if (${NTF_BUILD_WITH_INLINING_DISABLED}) + set(NTF_BUILD_WITH_INLINING_SUGGESTED FALSE CACHE INTERNAL "") + set(NTF_BUILD_WITH_INLINING_FORCED FALSE CACHE INTERNAL "") +endif() + +if (${NTF_BUILD_WITH_INLINING_FORCED}) + set(NTF_BUILD_WITH_INLINING_DISABLED FALSE CACHE INTERNAL "") + set(NTF_BUILD_WITH_INLINING_SUGGESTED FALSE CACHE INTERNAL "") +endif() + +if (${NTF_BUILD_WITH_INLINING_SUGGESTED}) + set(NTF_BUILD_WITH_INLINING_DISABLED FALSE CACHE INTERNAL "") + set(NTF_BUILD_WITH_INLINING_FORCED FALSE CACHE INTERNAL "") +endif() + +if (NOT ${NTF_BUILD_WITH_INLINING_DISABLED} AND + NOT ${NTF_BUILD_WITH_INLINING_FORCED} AND + NOT ${NTF_BUILD_WITH_INLINING_SUGGESTED}) + set(NTF_BUILD_WITH_INLINING_FORCED TRUE CACHE INTERNAL "") +endif() + if (NOT DEFINED NTF_BUILD_WITH_BRANCH_PREDICTION) if (DEFINED NTF_CONFIGURE_WITH_BRANCH_PREDICTION) set(NTF_BUILD_WITH_BRANCH_PREDICTION @@ -632,6 +689,38 @@ if (NOT DEFINED NTF_BUILD_WITH_SPIN_LOCKS) endif() endif() +if (NOT DEFINED NTF_BUILD_WITH_USERSPACE_MUTEXES) + if (DEFINED NTF_CONFIGURE_WITH_USERSPACE_MUTEXES) + set(NTF_BUILD_WITH_USERSPACE_MUTEXES + ${NTF_CONFIGURE_WITH_USERSPACE_MUTEXES} CACHE INTERNAL "") + elseif (DEFINED ENV{NTF_CONFIGURE_WITH_USERSPACE_MUTEXES}) + set(NTF_BUILD_WITH_USERSPACE_MUTEXES + $ENV{NTF_CONFIGURE_WITH_USERSPACE_MUTEXES} CACHE INTERNAL "") + else() + if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + set(NTF_BUILD_WITH_USERSPACE_MUTEXES TRUE CACHE INTERNAL "") + else() + set(NTF_BUILD_WITH_USERSPACE_MUTEXES FALSE CACHE INTERNAL "") + endif() + endif() +endif() + +if (NOT DEFINED NTF_BUILD_WITH_SYSTEM_MUTEXES) + if (DEFINED NTF_CONFIGURE_WITH_SYSTEM_MUTEXES) + set(NTF_BUILD_WITH_SYSTEM_MUTEXES + ${NTF_CONFIGURE_WITH_SYSTEM_MUTEXES} CACHE INTERNAL "") + elseif (DEFINED ENV{NTF_CONFIGURE_WITH_SYSTEM_MUTEXES}) + set(NTF_BUILD_WITH_SYSTEM_MUTEXES + $ENV{NTF_CONFIGURE_WITH_SYSTEM_MUTEXES} CACHE INTERNAL "") + else() + if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + set(NTF_BUILD_WITH_SYSTEM_MUTEXES FALSE CACHE INTERNAL "") + else() + set(NTF_BUILD_WITH_SYSTEM_MUTEXES TRUE CACHE INTERNAL "") + endif() + endif() +endif() + if (NOT DEFINED NTF_BUILD_WITH_RECURSIVE_MUTEXES) if (DEFINED NTF_CONFIGURE_WITH_RECURSIVE_MUTEXES) set(NTF_BUILD_WITH_RECURSIVE_MUTEXES @@ -644,6 +733,41 @@ if (NOT DEFINED NTF_BUILD_WITH_RECURSIVE_MUTEXES) endif() endif() +if (${NTF_BUILD_WITH_SPIN_LOCKS}) + set(NTF_BUILD_WITH_USERSPACE_MUTEXES FALSE CACHE INTERNAL "") + set(NTF_BUILD_WITH_SYSTEM_MUTEXES FALSE CACHE INTERNAL "") + set(NTF_BUILD_WITH_RECURSIVE_MUTEXES FALSE CACHE INTERNAL "") +endif() + +if (${NTF_BUILD_WITH_USERSPACE_MUTEXES}) + set(NTF_BUILD_WITH_SPIN_LOCKS FALSE CACHE INTERNAL "") + set(NTF_BUILD_WITH_SYSTEM_MUTEXES FALSE CACHE INTERNAL "") + set(NTF_BUILD_WITH_RECURSIVE_MUTEXES FALSE CACHE INTERNAL "") +endif() + +if (${NTF_BUILD_WITH_SYSTEM_MUTEXES}) + set(NTF_BUILD_WITH_SPIN_LOCKS FALSE CACHE INTERNAL "") + set(NTF_BUILD_WITH_USERSPACE_MUTEXES FALSE CACHE INTERNAL "") + set(NTF_BUILD_WITH_RECURSIVE_MUTEXES FALSE CACHE INTERNAL "") +endif() + +if (${NTF_BUILD_WITH_RECURSIVE_MUTEXES}) + set(NTF_BUILD_WITH_SPIN_LOCKS FALSE CACHE INTERNAL "") + set(NTF_BUILD_WITH_USERSPACE_MUTEXES FALSE CACHE INTERNAL "") + set(NTF_BUILD_WITH_SYSTEM_MUTEXES FALSE CACHE INTERNAL "") +endif() + +if (NOT ${NTF_BUILD_WITH_SPIN_LOCKS} AND + NOT ${NTF_BUILD_WITH_USERSPACE_MUTEXES} AND + NOT ${NTF_BUILD_WITH_SYSTEM_MUTEXES} AND + NOT ${NTF_BUILD_WITH_RECURSIVE_MUTEXES}) + if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + set(NTF_BUILD_WITH_USERSPACE_MUTEXES TRUE CACHE INTERNAL "") + else() + set(NTF_BUILD_WITH_SYSTEM_MUTEXES TRUE CACHE INTERNAL "") + endif() +endif() + # Convert NTF_BUILD_* "boolean" variables into 0 or 1 for suitability for # use in generating the configuration headers. @@ -859,6 +983,24 @@ else() message(STATUS "NTF: Building with metrics: no") endif() +if (${NTF_BUILD_WITH_INLINING_SUGGESTED}) + message(STATUS "NTF: Building with inlining suggested: yes") +else() + message(STATUS "NTF: Building with inlining suggested: no") +endif() + +if (${NTF_BUILD_WITH_INLINING_FORCED}) + message(STATUS "NTF: Building with inlining forced: yes") +else() + message(STATUS "NTF: Building with inlining forced: no") +endif() + +if (${NTF_BUILD_WITH_INLINING_DISABLED}) + message(STATUS "NTF: Building with inlining disabled: yes") +else() + message(STATUS "NTF: Building with inlining disabled: no") +endif() + if (${NTF_BUILD_WITH_BRANCH_PREDICTION}) message(STATUS "NTF: Building with branch prediction: yes") else() @@ -871,6 +1013,18 @@ else() message(STATUS "NTF: Building with spin locks: no") endif() +if (${NTF_BUILD_WITH_USERSPACE_MUTEXES}) + message(STATUS "NTF: Building with userspace mutexes: yes") +else() + message(STATUS "NTF: Building with userspace mutexes: no") +endif() + +if (${NTF_BUILD_WITH_SYSTEM_MUTEXES}) + message(STATUS "NTF: Building with system mutexes: yes") +else() + message(STATUS "NTF: Building with system mutexes: no") +endif() + if (${NTF_BUILD_WITH_RECURSIVE_MUTEXES}) message(STATUS "NTF: Building with recursive mutexes: yes") else()