| //===----------------------------------------------------------------------===// | 
 | // | 
 | // 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 |