| //===----------------------------------------------------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef TEST_BENCHMARK_ATOMIC_WAIT_HELPER_H |
| #define TEST_BENCHMARK_ATOMIC_WAIT_HELPER_H |
| |
| #include <atomic> |
| #include <chrono> |
| #include <exception> |
| #include <stop_token> |
| #include <thread> |
| |
| struct HighPrioTask { |
| sched_param param; |
| pthread_attr_t attr_t; |
| pthread_t thread; |
| std::atomic_bool stopped{false}; |
| |
| HighPrioTask(const HighPrioTask&) = delete; |
| |
| HighPrioTask() { |
| pthread_attr_init(&attr_t); |
| pthread_attr_setschedpolicy(&attr_t, SCHED_FIFO); |
| param.sched_priority = sched_get_priority_max(SCHED_FIFO); |
| pthread_attr_setschedparam(&attr_t, ¶m); |
| pthread_attr_setinheritsched(&attr_t, PTHREAD_EXPLICIT_SCHED); |
| |
| auto thread_fun = [](void* arg) -> void* { |
| auto* stop = reinterpret_cast<std::atomic_bool*>(arg); |
| while (!stop->load(std::memory_order_relaxed)) { |
| // spin |
| } |
| return nullptr; |
| }; |
| |
| if (pthread_create(&thread, &attr_t, thread_fun, &stopped) != 0) { |
| throw std::runtime_error("failed to create thread"); |
| } |
| } |
| |
| ~HighPrioTask() { |
| stopped = true; |
| pthread_attr_destroy(&attr_t); |
| pthread_join(thread, nullptr); |
| } |
| }; |
| |
| template <std::size_t N> |
| struct NumHighPrioTasks { |
| static constexpr auto value = N; |
| }; |
| |
| template <std::size_t N> |
| struct NumWaitingThreads { |
| static constexpr auto value = N; |
| }; |
| |
| template <std::size_t N> |
| struct NumberOfAtomics { |
| static constexpr auto value = N; |
| }; |
| |
| struct KeepNotifying { |
| template <class Atomic> |
| static void notify(Atomic& a, std::stop_token st) { |
| while (!st.stop_requested()) { |
| a.fetch_add(1, std::memory_order_relaxed); |
| a.notify_all(); |
| } |
| } |
| }; |
| |
| template <std::size_t N> |
| struct NotifyEveryNus { |
| template <class Atomic> |
| static void notify(Atomic& a, std::stop_token st) { |
| while (!st.stop_requested()) { |
| auto start = std::chrono::system_clock::now(); |
| a.fetch_add(1, std::memory_order_relaxed); |
| a.notify_all(); |
| while (std::chrono::system_clock::now() - start < std::chrono::microseconds{N}) { |
| } |
| } |
| } |
| }; |
| |
| #endif // TEST_BENCHMARK_ATOMIC_WAIT_HELPER_H |