From d3182acc79e35fa2f52993cd75e80407ddabdc75 Mon Sep 17 00:00:00 2001 From: Mathias Kraus Date: Thu, 19 Sep 2024 23:06:57 +0200 Subject: [PATCH] iox-#2301 Add SpinSemaphore --- iceoryx_hoofs/CMakeLists.txt | 3 +- .../sync/include/iox/spin_semaphore.hpp | 86 ++++++++++++++ .../concurrent/sync/source/spin_semaphore.cpp | 112 ++++++++++++++++++ .../include/iox}/semaphore_interface.hpp | 30 +++-- .../include/iox/detail/semaphore_helper.hpp | 55 +++++++++ .../sync/include/iox/named_semaphore.hpp | 13 +- .../sync/include/iox/unnamed_semaphore.hpp | 13 +- .../posix/sync/source/named_semaphore.cpp | 18 ++- ...ore_interface.cpp => semaphore_helper.cpp} | 44 +++---- .../posix/sync/source/unnamed_semaphore.cpp | 25 +++- .../test_posix_semaphore_interface.cpp | 14 ++- .../condition_variable_data.hpp | 9 +- .../condition_variable_data.cpp | 2 +- 13 files changed, 371 insertions(+), 53 deletions(-) create mode 100644 iceoryx_hoofs/concurrent/sync/include/iox/spin_semaphore.hpp create mode 100644 iceoryx_hoofs/concurrent/sync/source/spin_semaphore.cpp rename iceoryx_hoofs/{posix/sync/include/iox/detail => design/include/iox}/semaphore_interface.hpp (79%) create mode 100644 iceoryx_hoofs/posix/sync/include/iox/detail/semaphore_helper.hpp rename iceoryx_hoofs/posix/sync/source/{semaphore_interface.cpp => semaphore_helper.cpp} (57%) diff --git a/iceoryx_hoofs/CMakeLists.txt b/iceoryx_hoofs/CMakeLists.txt index f35d8705fb..7aa4487598 100644 --- a/iceoryx_hoofs/CMakeLists.txt +++ b/iceoryx_hoofs/CMakeLists.txt @@ -105,6 +105,7 @@ iox_add_library( cli/source/option_manager.cpp concurrent/buffer/source/mpmc_loffli.cpp concurrent/sync/source/spin_lock.cpp + concurrent/sync/source/spin_semaphore.cpp filesystem/source/file_reader.cpp filesystem/source/filesystem.cpp memory/source/bump_allocator.cpp @@ -135,7 +136,7 @@ iox_add_library( posix/sync/source/named_semaphore.cpp posix/sync/source/signal_handler.cpp posix/sync/source/signal_watcher.cpp - posix/sync/source/semaphore_interface.cpp + posix/sync/source/semaphore_helper.cpp posix/sync/source/thread.cpp posix/sync/source/unnamed_semaphore.cpp posix/time/source/adaptive_wait.cpp diff --git a/iceoryx_hoofs/concurrent/sync/include/iox/spin_semaphore.hpp b/iceoryx_hoofs/concurrent/sync/include/iox/spin_semaphore.hpp new file mode 100644 index 0000000000..134838731d --- /dev/null +++ b/iceoryx_hoofs/concurrent/sync/include/iox/spin_semaphore.hpp @@ -0,0 +1,86 @@ + +// Copyright (c) 2024 by ekxide IO GmbH. All rights reserved. +// +// 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. +// +// SPDX-License-Identifier: Apache-2.0 + +#ifndef IOX_HOOFS_CONCURRENT_SYNC_SPIN_SEMAPHORE_HPP +#define IOX_HOOFS_CONCURRENT_SYNC_SPIN_SEMAPHORE_HPP + +#include "iox/atomic.hpp" +#include "iox/deadline_timer.hpp" +#include "iox/detail/adaptive_wait.hpp" +#include "iox/optional.hpp" +#include "iox/semaphore_interface.hpp" +#include "iox/spin_lock.hpp" + +namespace iox +{ +namespace concurrent +{ +class SpinSemaphoreBuilder; + +class SpinSemaphore : public detail::SemaphoreInterface +{ + public: + using Builder = SpinSemaphoreBuilder; + + SpinSemaphore(const SpinSemaphore&) = delete; + SpinSemaphore(SpinSemaphore&&) = delete; + SpinSemaphore& operator=(const SpinSemaphore&) = delete; + SpinSemaphore& operator=(SpinSemaphore&&) = delete; + + ~SpinSemaphore() noexcept; + + private: + friend class optional; + friend class detail::SemaphoreInterface; + + explicit SpinSemaphore(int32_t initial_value) noexcept; + + expected post_impl() noexcept; + + expected wait_impl() noexcept; + + expected try_wait_impl() noexcept; + + expected timed_wait_impl(const units::Duration& timeout) noexcept; + + private: + concurrent::Atomic m_count{0}; + concurrent::Atomic m_to_be_destroyed{false}; + optional m_spinlock; +}; + +class SpinSemaphoreBuilder +{ + /// @brief Set the initial value of the spin semaphore + IOX_BUILDER_PARAMETER(uint32_t, initialValue, 0U) + + /// @brief Set if the spin semaphore can be stored in the shared memory + /// for inter process usage + IOX_BUILDER_PARAMETER(bool, isInterProcessCapable, true) + + public: + /// @brief Create a spin semaphore + /// @param[in] uninitializedSemaphore since the semaphore is not movable the user has to provide + /// memory to store the semaphore into - packed in an optional + /// @return an error describing the failure or success + expected create(optional& uninitializedSemaphore) const noexcept; +}; + +} // namespace concurrent +} // namespace iox + +#endif // IOX_HOOFS_CONCURRENT_SYNC_SPIN_LOCK_HPP diff --git a/iceoryx_hoofs/concurrent/sync/source/spin_semaphore.cpp b/iceoryx_hoofs/concurrent/sync/source/spin_semaphore.cpp new file mode 100644 index 0000000000..b09905b1f2 --- /dev/null +++ b/iceoryx_hoofs/concurrent/sync/source/spin_semaphore.cpp @@ -0,0 +1,112 @@ +// Copyright (c) 2024 by ekxide IO GmbH. All rights reserved. +// +// 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. +// +// SPDX-License-Identifier: Apache-2.0 + +#include "iox/spin_semaphore.hpp" +#include "iox/detail/adaptive_wait.hpp" + +namespace iox +{ +namespace concurrent +{ +expected +SpinSemaphoreBuilder::create(optional& uninitializedSemaphore) const noexcept +{ + if (m_initialValue > IOX_SEM_VALUE_MAX) + { + IOX_LOG(ERROR, + "The spin semaphore initial value of " << m_initialValue << " exceeds the maximum semaphore value " + << IOX_SEM_VALUE_MAX); + return err(SemaphoreError::SEMAPHORE_OVERFLOW); + } + + uninitializedSemaphore.emplace(static_cast(m_initialValue)); + return ok(); +} + +SpinSemaphore::SpinSemaphore(int32_t initial_value) noexcept + : m_count(initial_value) +{ + SpinLockBuilder() + .is_inter_process_capable(true) + .lock_behavior(LockBehavior::NORMAL) + .create(m_spinlock) + .expect("Failed to create Lock"); +} + +SpinSemaphore::~SpinSemaphore() noexcept +{ + m_to_be_destroyed = true; +} + +expected SpinSemaphore::post_impl() noexcept +{ + std::lock_guard lock(*m_spinlock); + + if (m_count.load(std::memory_order_relaxed) == IOX_SEM_VALUE_MAX) + { + return err(SemaphoreError::SEMAPHORE_OVERFLOW); + } + + ++m_count; + return ok(); +} + +expected SpinSemaphore::wait_impl() noexcept +{ + detail::adaptive_wait spinner; + spinner.wait_loop([this] { + auto wait_result = this->tryWait(); + return wait_result.has_value() && !wait_result.value(); + }); + return ok(); +} + +expected SpinSemaphore::try_wait_impl() noexcept +{ + std::lock_guard lock(*m_spinlock); + if (m_to_be_destroyed.load(std::memory_order_relaxed)) + { + return ok(true); + } + if (m_count.load(std::memory_order_relaxed) > 0) + { + --m_count; + return ok(true); + } + return ok(false); +} + +expected SpinSemaphore::timed_wait_impl(const units::Duration& timeout) noexcept +{ + iox::deadline_timer deadline_timer(timeout); + detail::adaptive_wait spinner; + + auto ret_val = SemaphoreWaitState::TIMEOUT; + spinner.wait_loop([this, &deadline_timer, &ret_val] { + auto wait_result = this->tryWait(); + + if (wait_result.has_value() && wait_result.value()) + { + ret_val = SemaphoreWaitState::NO_TIMEOUT; + return false; + } + return !deadline_timer.hasExpired(); + }); + + return ok(ret_val); +} +} // namespace concurrent +} // namespace iox diff --git a/iceoryx_hoofs/posix/sync/include/iox/detail/semaphore_interface.hpp b/iceoryx_hoofs/design/include/iox/semaphore_interface.hpp similarity index 79% rename from iceoryx_hoofs/posix/sync/include/iox/detail/semaphore_interface.hpp rename to iceoryx_hoofs/design/include/iox/semaphore_interface.hpp index 355d7fce08..aa634a7646 100644 --- a/iceoryx_hoofs/posix/sync/include/iox/detail/semaphore_interface.hpp +++ b/iceoryx_hoofs/design/include/iox/semaphore_interface.hpp @@ -1,4 +1,5 @@ // Copyright (c) 2022 by Apex.AI Inc. All rights reserved. +// Copyright (c) 2024 by ekxide IO GmbH. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,8 +15,8 @@ // // SPDX-License-Identifier: Apache-2.0 -#ifndef IOX_HOOFS_POSIX_SYNC_SEMAPHORE_INTERFACE_HPP -#define IOX_HOOFS_POSIX_SYNC_SEMAPHORE_INTERFACE_HPP +#ifndef IOX_HOOFS_DESIGN_SEMAPHORE_INTERFACE_HPP +#define IOX_HOOFS_DESIGN_SEMAPHORE_INTERFACE_HPP #include "iceoryx_platform/semaphore.hpp" #include "iox/duration.hpp" @@ -59,32 +60,41 @@ class SemaphoreInterface /// @brief Increments the semaphore by one /// @return Fails when the value of the semaphore overflows or when the /// semaphore was removed from outside the process - expected post() noexcept; + expected post() noexcept + { + return static_cast(this)->post_impl(); + } /// @brief Decrements the semaphore by one. When the semaphore value is zero /// it blocks until the semaphore value is greater zero /// @return Fails when semaphore was removed from outside the process - expected wait() noexcept; + expected wait() noexcept + { + return static_cast(this)->wait_impl(); + } /// @brief Tries to decrement the semaphore by one. When the semaphore value is zero /// it returns false otherwise it returns true and decrement the value by one. /// @return Fails when semaphore was removed from outside the process - expected tryWait() noexcept; + expected tryWait() noexcept + { + return static_cast(this)->try_wait_impl(); + } /// @brief Tries to decrement the semaphore by one. When the semaphore value is zero /// it waits until the timeout has passed. /// @return If during the timeout time the semaphore value increases to non zero /// it returns SemaphoreWaitState::NO_TIMEOUT and decreases the semaphore by one /// otherwise returns SemaphoreWaitState::TIMEOUT - expected timedWait(const units::Duration& timeout) noexcept; + expected timedWait(const units::Duration& timeout) noexcept + { + return static_cast(this)->timed_wait_impl(timeout); + } protected: SemaphoreInterface() noexcept = default; - - private: - iox_sem_t* getHandle() noexcept; }; } // namespace detail } // namespace iox -#endif // IOX_HOOFS_POSIX_SYNC_SEMAPHORE_INTERFACE_HPP +#endif // IOX_HOOFS_DESIGN_SEMAPHORE_INTERFACE_HPP diff --git a/iceoryx_hoofs/posix/sync/include/iox/detail/semaphore_helper.hpp b/iceoryx_hoofs/posix/sync/include/iox/detail/semaphore_helper.hpp new file mode 100644 index 0000000000..e7084ebc02 --- /dev/null +++ b/iceoryx_hoofs/posix/sync/include/iox/detail/semaphore_helper.hpp @@ -0,0 +1,55 @@ +// Copyright (c) 2022 by Apex.AI Inc. All rights reserved. +// Copyright (c) 2024 by ekxide IO GmbH. All rights reserved. +// +// 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. +// +// SPDX-License-Identifier: Apache-2.0 + +#ifndef IOX_HOOFS_POSIX_SYNC_SEMAPHORE_HELPER_HPP +#define IOX_HOOFS_POSIX_SYNC_SEMAPHORE_HELPER_HPP + +#include "iceoryx_platform/semaphore.hpp" +#include "iox/duration.hpp" +#include "iox/expected.hpp" +#include "iox/semaphore_interface.hpp" + +namespace iox +{ +namespace detail +{ +/// @brief Increments the semaphore by one +/// @return Fails when the value of the semaphore overflows or when the +/// semaphore was removed from outside the process +expected sem_post(iox_sem_t* handle) noexcept; + +/// @brief Decrements the semaphore by one. When the semaphore value is zero +/// it blocks until the semaphore value is greater zero +/// @return Fails when semaphore was removed from outside the process +expected sem_wait(iox_sem_t* handle) noexcept; + +/// @brief Tries to decrement the semaphore by one. When the semaphore value is zero +/// it returns false otherwise it returns true and decrement the value by one. +/// @return Fails when semaphore was removed from outside the process +expected sem_try_wait(iox_sem_t* handle) noexcept; + +/// @brief Tries to decrement the semaphore by one. When the semaphore value is zero +/// it waits until the timeout has passed. +/// @return If during the timeout time the semaphore value increases to non zero +/// it returns SemaphoreWaitState::NO_TIMEOUT and decreases the semaphore by one +/// otherwise returns SemaphoreWaitState::TIMEOUT +expected sem_timed_wait(iox_sem_t* handle, const units::Duration& timeout) noexcept; + +} // namespace detail +} // namespace iox + +#endif // IOX_HOOFS_POSIX_SYNC_SEMAPHORE_HELPER_HPP diff --git a/iceoryx_hoofs/posix/sync/include/iox/named_semaphore.hpp b/iceoryx_hoofs/posix/sync/include/iox/named_semaphore.hpp index ce73d474c0..0e71345139 100644 --- a/iceoryx_hoofs/posix/sync/include/iox/named_semaphore.hpp +++ b/iceoryx_hoofs/posix/sync/include/iox/named_semaphore.hpp @@ -1,4 +1,5 @@ // Copyright (c) 2022 by Apex.AI Inc. All rights reserved. +// Copyright (c) 2024 by ekxide IO GmbH. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,18 +20,22 @@ #include "iceoryx_platform/platform_settings.hpp" #include "iox/builder.hpp" -#include "iox/detail/semaphore_interface.hpp" #include "iox/expected.hpp" #include "iox/filesystem.hpp" #include "iox/optional.hpp" +#include "iox/semaphore_interface.hpp" #include "iox/string.hpp" namespace iox { +class NamedSemaphoreBuilder; + /// @brief A named posix semaphore. class NamedSemaphore final : public detail::SemaphoreInterface { public: + using Builder = NamedSemaphoreBuilder; + static constexpr uint64_t LENGTH_OF_SEMAPHORE_SLASH_PREFIX = 1U; using Name_t = string; @@ -46,7 +51,11 @@ class NamedSemaphore final : public detail::SemaphoreInterface friend class detail::SemaphoreInterface; NamedSemaphore(iox_sem_t* handle, const Name_t& name, const bool hasOwnership) noexcept; - iox_sem_t* getHandle() noexcept; + + expected post_impl() noexcept; + expected wait_impl() noexcept; + expected try_wait_impl() noexcept; + expected timed_wait_impl(const units::Duration& timeout) noexcept; iox_sem_t* m_handle = nullptr; Name_t m_name; diff --git a/iceoryx_hoofs/posix/sync/include/iox/unnamed_semaphore.hpp b/iceoryx_hoofs/posix/sync/include/iox/unnamed_semaphore.hpp index c9898e8eca..1e419a4483 100644 --- a/iceoryx_hoofs/posix/sync/include/iox/unnamed_semaphore.hpp +++ b/iceoryx_hoofs/posix/sync/include/iox/unnamed_semaphore.hpp @@ -1,4 +1,5 @@ // Copyright (c) 2022 by Apex.AI Inc. All rights reserved. +// Copyright (c) 2024 by ekxide IO GmbH. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -18,12 +19,14 @@ #define IOX_HOOFS_POSIX_SYNC_UNNAMED_SEMAPHORE_HPP #include "iox/builder.hpp" -#include "iox/detail/semaphore_interface.hpp" #include "iox/expected.hpp" #include "iox/optional.hpp" +#include "iox/semaphore_interface.hpp" namespace iox { +class UnnamedSemaphoreBuilder; + /// @brief A unnamed posix semaphore. // NOLINTJUSTIFICATION m_handle is always initialized during create in the UnnamedSemaphoreBuilder // hence it is impossible to create a UnnamedSemaphore without an initialized @@ -32,6 +35,8 @@ namespace iox class UnnamedSemaphore final : public detail::SemaphoreInterface { public: + using Builder = UnnamedSemaphoreBuilder; + UnnamedSemaphore(const UnnamedSemaphore&) noexcept = delete; UnnamedSemaphore(UnnamedSemaphore&&) noexcept = delete; UnnamedSemaphore& operator=(const UnnamedSemaphore&) noexcept = delete; @@ -44,7 +49,11 @@ class UnnamedSemaphore final : public detail::SemaphoreInterface; UnnamedSemaphore() noexcept = default; - iox_sem_t* getHandle() noexcept; + + expected post_impl() noexcept; + expected wait_impl() noexcept; + expected try_wait_impl() noexcept; + expected timed_wait_impl(const units::Duration& timeout) noexcept; iox_sem_t m_handle; bool m_destroyHandle = true; diff --git a/iceoryx_hoofs/posix/sync/source/named_semaphore.cpp b/iceoryx_hoofs/posix/sync/source/named_semaphore.cpp index 01eb583db0..552df47414 100644 --- a/iceoryx_hoofs/posix/sync/source/named_semaphore.cpp +++ b/iceoryx_hoofs/posix/sync/source/named_semaphore.cpp @@ -1,4 +1,5 @@ // Copyright (c) 2022 by Apex.AI Inc. All rights reserved. +// Copyright (c) 2024 by ekxide IO GmbH. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,6 +16,7 @@ // SPDX-License-Identifier: Apache-2.0 #include "iox/named_semaphore.hpp" +#include "iox/detail/semaphore_helper.hpp" #include "iox/logging.hpp" #include "iox/posix_call.hpp" @@ -239,8 +241,20 @@ NamedSemaphore::~NamedSemaphore() noexcept } } -iox_sem_t* NamedSemaphore::getHandle() noexcept +expected NamedSemaphore::post_impl() noexcept { - return m_handle; + return detail::sem_post(m_handle); +} +expected NamedSemaphore::wait_impl() noexcept +{ + return detail::sem_wait(m_handle); +} +expected NamedSemaphore::try_wait_impl() noexcept +{ + return detail::sem_try_wait(m_handle); +} +expected NamedSemaphore::timed_wait_impl(const units::Duration& timeout) noexcept +{ + return detail::sem_timed_wait(m_handle, timeout); } } // namespace iox diff --git a/iceoryx_hoofs/posix/sync/source/semaphore_interface.cpp b/iceoryx_hoofs/posix/sync/source/semaphore_helper.cpp similarity index 57% rename from iceoryx_hoofs/posix/sync/source/semaphore_interface.cpp rename to iceoryx_hoofs/posix/sync/source/semaphore_helper.cpp index 3d84d9ad78..a5c20ab5e1 100644 --- a/iceoryx_hoofs/posix/sync/source/semaphore_interface.cpp +++ b/iceoryx_hoofs/posix/sync/source/semaphore_helper.cpp @@ -1,4 +1,5 @@ // Copyright (c) 2022 by Apex.AI Inc. All rights reserved. +// Copyright (c) 2024 by ekxide IO GmbH. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,17 +15,15 @@ // // SPDX-License-Identifier: Apache-2.0 -#include "iox/detail/semaphore_interface.hpp" +#include "iox/detail/semaphore_helper.hpp" #include "iox/logging.hpp" -#include "iox/named_semaphore.hpp" #include "iox/posix_call.hpp" -#include "iox/unnamed_semaphore.hpp" namespace iox { namespace detail { -SemaphoreError errnoToEnum(const int32_t errnum) noexcept +SemaphoreError sem_errno_to_enum(const int32_t errnum) noexcept { switch (errnum) { @@ -44,70 +43,57 @@ SemaphoreError errnoToEnum(const int32_t errnum) noexcept return SemaphoreError::UNDEFINED; } -template -iox_sem_t* SemaphoreInterface::getHandle() noexcept +expected sem_post(iox_sem_t* handle) noexcept { - return static_cast(this)->getHandle(); -} - -template -expected SemaphoreInterface::post() noexcept -{ - auto result = IOX_POSIX_CALL(iox_sem_post)(getHandle()).failureReturnValue(-1).evaluate(); + auto result = IOX_POSIX_CALL(iox_sem_post)(handle).failureReturnValue(-1).evaluate(); if (result.has_error()) { - return err(errnoToEnum(result.error().errnum)); + return err(sem_errno_to_enum(result.error().errnum)); } return ok(); } -template -expected -SemaphoreInterface::timedWait(const units::Duration& timeout) noexcept +expected sem_timed_wait(iox_sem_t* handle, const units::Duration& timeout) noexcept { const timespec timeoutAsTimespec = timeout.timespec(units::TimeSpecReference::Epoch); - auto result = IOX_POSIX_CALL(iox_sem_timedwait)(getHandle(), &timeoutAsTimespec) + auto result = IOX_POSIX_CALL(iox_sem_timedwait)(handle, &timeoutAsTimespec) .failureReturnValue(-1) .ignoreErrnos(ETIMEDOUT) .evaluate(); if (result.has_error()) { - return err(errnoToEnum(result.error().errnum)); + return err(sem_errno_to_enum(result.error().errnum)); } return ok((result.value().errnum == ETIMEDOUT) ? SemaphoreWaitState::TIMEOUT : SemaphoreWaitState::NO_TIMEOUT); } -template -expected SemaphoreInterface::tryWait() noexcept +expected sem_try_wait(iox_sem_t* handle) noexcept { - auto result = IOX_POSIX_CALL(iox_sem_trywait)(getHandle()).failureReturnValue(-1).ignoreErrnos(EAGAIN).evaluate(); + auto result = IOX_POSIX_CALL(iox_sem_trywait)(handle).failureReturnValue(-1).ignoreErrnos(EAGAIN).evaluate(); if (result.has_error()) { - return err(errnoToEnum(result.error().errnum)); + return err(sem_errno_to_enum(result.error().errnum)); } return ok(result.value().errnum != EAGAIN); } -template -expected SemaphoreInterface::wait() noexcept +expected sem_wait(iox_sem_t* handle) noexcept { - auto result = IOX_POSIX_CALL(iox_sem_wait)(getHandle()).failureReturnValue(-1).evaluate(); + auto result = IOX_POSIX_CALL(iox_sem_wait)(handle).failureReturnValue(-1).evaluate(); if (result.has_error()) { - return err(errnoToEnum(result.error().errnum)); + return err(sem_errno_to_enum(result.error().errnum)); } return ok(); } -template class SemaphoreInterface; -template class SemaphoreInterface; } // namespace detail } // namespace iox diff --git a/iceoryx_hoofs/posix/sync/source/unnamed_semaphore.cpp b/iceoryx_hoofs/posix/sync/source/unnamed_semaphore.cpp index 058ded3670..a32910beb2 100644 --- a/iceoryx_hoofs/posix/sync/source/unnamed_semaphore.cpp +++ b/iceoryx_hoofs/posix/sync/source/unnamed_semaphore.cpp @@ -1,4 +1,5 @@ // Copyright (c) 2022 by Apex.AI Inc. All rights reserved. +// Copyright (c) 2024 by ekxide IO GmbH. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,6 +16,7 @@ // SPDX-License-Identifier: Apache-2.0 #include "iox/unnamed_semaphore.hpp" +#include "iox/detail/semaphore_helper.hpp" #include "iox/logging.hpp" #include "iox/posix_call.hpp" @@ -65,7 +67,7 @@ UnnamedSemaphore::~UnnamedSemaphore() noexcept { if (m_destroyHandle) { - auto result = IOX_POSIX_CALL(iox_sem_destroy)(getHandle()).failureReturnValue(-1).evaluate(); + auto result = IOX_POSIX_CALL(iox_sem_destroy)(&m_handle).failureReturnValue(-1).evaluate(); if (result.has_error()) { switch (result.error().errnum) @@ -81,8 +83,25 @@ UnnamedSemaphore::~UnnamedSemaphore() noexcept } } -iox_sem_t* UnnamedSemaphore::getHandle() noexcept + +expected UnnamedSemaphore::post_impl() noexcept +{ + return detail::sem_post(&m_handle); +} + +expected UnnamedSemaphore::wait_impl() noexcept { - return &m_handle; + return detail::sem_wait(&m_handle); } + +expected UnnamedSemaphore::try_wait_impl() noexcept +{ + return detail::sem_try_wait(&m_handle); +} + +expected UnnamedSemaphore::timed_wait_impl(const units::Duration& timeout) noexcept +{ + return detail::sem_timed_wait(&m_handle, timeout); +} + } // namespace iox diff --git a/iceoryx_hoofs/test/moduletests/test_posix_semaphore_interface.cpp b/iceoryx_hoofs/test/moduletests/test_posix_semaphore_interface.cpp index 8f0ae6b1a5..087413da8d 100644 --- a/iceoryx_hoofs/test/moduletests/test_posix_semaphore_interface.cpp +++ b/iceoryx_hoofs/test/moduletests/test_posix_semaphore_interface.cpp @@ -20,9 +20,10 @@ #include "iceoryx_hoofs/testing/watch_dog.hpp" #include "iceoryx_platform/platform_settings.hpp" #include "iceoryx_platform/time.hpp" -#include "iox/detail/semaphore_interface.hpp" #include "iox/duration.hpp" #include "iox/named_semaphore.hpp" +#include "iox/semaphore_interface.hpp" +#include "iox/spin_semaphore.hpp" #include "iox/unnamed_semaphore.hpp" #include "test.hpp" @@ -96,7 +97,16 @@ struct NamedSemaphoreTest } }; -using Implementations = Types; +struct SpinSemaphoreTest +{ + using SutType = iox::optional; + static iox::expected create(SutType& sut, const uint32_t initialValue) + { + return concurrent::SpinSemaphoreBuilder().initialValue(initialValue).isInterProcessCapable(false).create(sut); + } +}; + +using Implementations = Types; TYPED_TEST_SUITE(SemaphoreInterfaceTest, Implementations, ); diff --git a/iceoryx_posh/include/iceoryx_posh/internal/popo/building_blocks/condition_variable_data.hpp b/iceoryx_posh/include/iceoryx_posh/internal/popo/building_blocks/condition_variable_data.hpp index 532539c19a..787c9926c2 100644 --- a/iceoryx_posh/include/iceoryx_posh/internal/popo/building_blocks/condition_variable_data.hpp +++ b/iceoryx_posh/include/iceoryx_posh/internal/popo/building_blocks/condition_variable_data.hpp @@ -20,12 +20,19 @@ #include "iceoryx_posh/iceoryx_posh_types.hpp" #include "iceoryx_posh/internal/posh_error_reporting.hpp" #include "iox/atomic.hpp" +#include "iox/spin_semaphore.hpp" #include "iox/unnamed_semaphore.hpp" namespace iox { namespace popo { +#ifdef IOX_EXPERIMENTAL_32_64_BIT_MIX_MODE +using InterProcessSemaphore = concurrent::SpinSemaphore; +#else +using InterProcessSemaphore = UnnamedSemaphore; +#endif + struct ConditionVariableData { ConditionVariableData() noexcept; @@ -37,7 +44,7 @@ struct ConditionVariableData ConditionVariableData& operator=(ConditionVariableData&& rhs) = delete; ~ConditionVariableData() noexcept = default; - optional m_semaphore; + optional m_semaphore; RuntimeName_t m_runtimeName; concurrent::Atomic m_toBeDestroyed{false}; concurrent::Atomic m_activeNotifications[MAX_NUMBER_OF_NOTIFIERS]; diff --git a/iceoryx_posh/source/popo/building_blocks/condition_variable_data.cpp b/iceoryx_posh/source/popo/building_blocks/condition_variable_data.cpp index 9b786c5399..eacdc20597 100644 --- a/iceoryx_posh/source/popo/building_blocks/condition_variable_data.cpp +++ b/iceoryx_posh/source/popo/building_blocks/condition_variable_data.cpp @@ -30,7 +30,7 @@ ConditionVariableData::ConditionVariableData() noexcept ConditionVariableData::ConditionVariableData(const RuntimeName_t& runtimeName) noexcept : m_runtimeName(runtimeName) { - UnnamedSemaphoreBuilder().initialValue(0U).isInterProcessCapable(true).create(m_semaphore).or_else([](auto) { + InterProcessSemaphore::Builder().initialValue(0U).isInterProcessCapable(true).create(m_semaphore).or_else([](auto) { IOX_REPORT_FATAL(PoshError::POPO__CONDITION_VARIABLE_DATA_FAILED_TO_CREATE_SEMAPHORE); });