From 0abcf7ea6ffdf90f4d8c240cd932018ee5186fcd Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Fri, 2 Oct 2020 17:41:12 +0200 Subject: [PATCH 1/2] Introduce SpinLock --- lib/base/CMakeLists.txt | 1 + lib/base/spinlock.cpp | 22 ++++++++++++++++++++++ lib/base/spinlock.hpp | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 lib/base/spinlock.cpp create mode 100644 lib/base/spinlock.hpp diff --git a/lib/base/CMakeLists.txt b/lib/base/CMakeLists.txt index 3e4d8a7cf..20507ac7f 100644 --- a/lib/base/CMakeLists.txt +++ b/lib/base/CMakeLists.txt @@ -63,6 +63,7 @@ set(base_SOURCES shared.hpp singleton.hpp socket.cpp socket.hpp + spinlock.cpp spinlock.hpp stacktrace.cpp stacktrace.hpp statsfunction.hpp stdiostream.cpp stdiostream.hpp diff --git a/lib/base/spinlock.cpp b/lib/base/spinlock.cpp new file mode 100644 index 000000000..03de2e6be --- /dev/null +++ b/lib/base/spinlock.cpp @@ -0,0 +1,22 @@ +/* Icinga 2 | (c) 2020 Icinga GmbH | GPLv2+ */ + +#include "base/spinlock.hpp" +#include + +using namespace icinga; + +void SpinLock::lock() +{ + while (m_Locked.test_and_set(std::memory_order_acquire)) { + } +} + +bool SpinLock::try_lock() +{ + return !m_Locked.test_and_set(std::memory_order_acquire); +} + +void SpinLock::unlock() +{ + m_Locked.clear(std::memory_order_release); +} diff --git a/lib/base/spinlock.hpp b/lib/base/spinlock.hpp new file mode 100644 index 000000000..d6da5876e --- /dev/null +++ b/lib/base/spinlock.hpp @@ -0,0 +1,35 @@ +/* Icinga 2 | (c) 2020 Icinga GmbH | GPLv2+ */ + +#ifndef SPINLOCK_H +#define SPINLOCK_H + +#include + +namespace icinga +{ + +/** + * A spin lock. + * + * @ingroup base + */ +class SpinLock +{ +public: + SpinLock() = default; + SpinLock(const SpinLock&) = delete; + SpinLock& operator=(const SpinLock&) = delete; + SpinLock(SpinLock&&) = delete; + SpinLock& operator=(SpinLock&&) = delete; + + void lock(); + bool try_lock(); + void unlock(); + +private: + std::atomic_flag m_Locked = ATOMIC_FLAG_INIT; +}; + +} + +#endif /* SPINLOCK_H */ From b6b3ac0ab8700479fde6e0406c14eddcd2f489b9 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Fri, 2 Oct 2020 17:53:17 +0200 Subject: [PATCH 2/2] Make ApiListener::m_ConfigSyncStageLock a SpinLock --- lib/remote/apilistener-filesync.cpp | 6 +++--- lib/remote/apilistener.hpp | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/remote/apilistener-filesync.cpp b/lib/remote/apilistener-filesync.cpp index ab1d5c728..28d903c19 100644 --- a/lib/remote/apilistener-filesync.cpp +++ b/lib/remote/apilistener-filesync.cpp @@ -20,7 +20,7 @@ using namespace icinga; REGISTER_APIFUNCTION(Update, config, &ApiListener::ConfigUpdateHandler); -boost::mutex ApiListener::m_ConfigSyncStageLock; +SpinLock ApiListener::m_ConfigSyncStageLock; /** * Entrypoint for updating all authoritative configs from /etc/zones.d, packages, etc. @@ -321,7 +321,7 @@ void ApiListener::HandleConfigUpdate(const MessageOrigin::Ptr& origin, const Dic /* Only one transaction is allowed, concurrent message handlers need to wait. * This affects two parent endpoints sending the config in the same moment. */ - auto lock (Shared::Make(m_ConfigSyncStageLock)); + auto lock (Shared>::Make(m_ConfigSyncStageLock)); String apiZonesStageDir = GetApiZonesStageDir(); String fromEndpointName = origin->FromClient->GetEndpoint()->GetName(); @@ -618,7 +618,7 @@ void ApiListener::TryActivateZonesStageCallback(const ProcessResult& pr, * * @param relativePaths Required for later file operations in the callback. Provides the zone name plus path in a list. */ -void ApiListener::AsyncTryActivateZonesStage(const std::vector& relativePaths, const Shared::Ptr& lock) +void ApiListener::AsyncTryActivateZonesStage(const std::vector& relativePaths, const Shared>::Ptr& lock) { VERIFY(Application::GetArgC() >= 1); diff --git a/lib/remote/apilistener.hpp b/lib/remote/apilistener.hpp index e3a1b0d9a..86a98d23a 100644 --- a/lib/remote/apilistener.hpp +++ b/lib/remote/apilistener.hpp @@ -11,6 +11,7 @@ #include "base/configobject.hpp" #include "base/process.hpp" #include "base/shared.hpp" +#include "base/spinlock.hpp" #include "base/timer.hpp" #include "base/workqueue.hpp" #include "base/tcpsocket.hpp" @@ -20,6 +21,7 @@ #include #include #include +#include #include namespace icinga @@ -179,7 +181,7 @@ private: void RemoveStatusFile(); /* filesync */ - static boost::mutex m_ConfigSyncStageLock; + static SpinLock m_ConfigSyncStageLock; void SyncLocalZoneDirs() const; void SyncLocalZoneDir(const Zone::Ptr& zone) const; @@ -193,7 +195,7 @@ private: static void TryActivateZonesStageCallback(const ProcessResult& pr, const std::vector& relativePaths); - static void AsyncTryActivateZonesStage(const std::vector& relativePaths, const Shared::Ptr& lock); + static void AsyncTryActivateZonesStage(const std::vector& relativePaths, const Shared>::Ptr& lock); static String GetChecksum(const String& content); static bool CheckConfigChange(const ConfigDirInformation& oldConfig, const ConfigDirInformation& newConfig);