thread_pause.hpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /*
  2. * Distributed under the Boost Software License, Version 1.0.
  3. * (See accompanying file LICENSE_1_0.txt or copy at
  4. * http://www.boost.org/LICENSE_1_0.txt)
  5. *
  6. * (C) Copyright 2013 Tim Blechmann
  7. * (C) Copyright 2013, 2020-2025 Andrey Semashev
  8. */
  9. #ifndef BOOST_ATOMIC_THREAD_PAUSE_HPP_INCLUDED_
  10. #define BOOST_ATOMIC_THREAD_PAUSE_HPP_INCLUDED_
  11. #include <boost/atomic/detail/config.hpp>
  12. #if defined(_MSC_VER)
  13. #include <boost/atomic/detail/ops_msvc_common.hpp>
  14. #endif
  15. #include <boost/atomic/detail/header.hpp>
  16. #ifdef BOOST_HAS_PRAGMA_ONCE
  17. #pragma once
  18. #endif
  19. #if defined(_MSC_VER)
  20. // (sigh, shake head) _M_ARM64EC and _M_AMD64 may be defined both
  21. // https://learn.microsoft.com/en-us/windows/arm/arm64ec-abi
  22. #if defined(_M_ARM64) || defined(_M_ARM64EC)
  23. extern "C" void __isb(unsigned int);
  24. #if defined(BOOST_MSVC)
  25. #pragma intrinsic(__isb)
  26. #endif
  27. #elif defined(_M_ARM)
  28. extern "C" void __yield(void);
  29. #if defined(BOOST_MSVC)
  30. #pragma intrinsic(__yield)
  31. #endif
  32. #elif defined(_M_AMD64) || defined(_M_IX86)
  33. extern "C" void _mm_pause(void);
  34. #if defined(BOOST_MSVC)
  35. #pragma intrinsic(_mm_pause)
  36. #endif
  37. #endif
  38. #endif
  39. #if defined(sun) || defined(__sun)
  40. // Avoid including synch.h
  41. extern "C" void smt_pause(void);
  42. #endif
  43. namespace boost {
  44. namespace atomics {
  45. //! The function pauses for a number of CPU cycles, potentially freeing CPU resources, allowing sibling threads to progress. May be a no-op.
  46. BOOST_FORCEINLINE void thread_pause() noexcept
  47. {
  48. #if defined(_MSC_VER)
  49. BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
  50. #if defined(_M_ARM64) || defined(_M_ARM64EC)
  51. __isb(0xF); // ISB SY
  52. #elif defined(_M_ARM)
  53. __yield();
  54. #elif defined(_M_AMD64) || defined(_M_IX86)
  55. _mm_pause();
  56. #endif
  57. BOOST_ATOMIC_DETAIL_COMPILER_BARRIER();
  58. #elif defined(__GNUC__)
  59. #if defined(__i386__) || defined(__x86_64__)
  60. __asm__ __volatile__("pause" : : : "memory");
  61. #elif defined(__aarch64__)
  62. // https://github.com/rust-lang/rust/commit/c064b6560b7ce0adeb9bbf5d7dcf12b1acb0c807
  63. // https://web.archive.org/web/20231004132033/https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8258604
  64. __asm__ __volatile__("isb" : : : "memory");
  65. #elif (defined(__ARM_ARCH) && __ARM_ARCH >= 8) || defined(__ARM_ARCH_8A__)
  66. __asm__ __volatile__("yield" : : : "memory");
  67. #elif (defined(__POWERPC__) || defined(__PPC__))
  68. __asm__ __volatile__("or 27,27,27" : : : "memory"); // yield pseudo-instruction
  69. #elif defined(__riscv) && (__riscv_xlen == 64)
  70. #if defined(__riscv_zihintpause)
  71. __asm__ __volatile__("pause" : : : "memory");
  72. #else
  73. // Encoding of the pause instruction
  74. __asm__ __volatile__ (".4byte 0x100000F" : : : "memory");
  75. #endif
  76. #elif defined(sun) || defined(__sun)
  77. smt_pause();
  78. #endif
  79. #elif defined(sun) || defined(__sun)
  80. smt_pause();
  81. #endif
  82. }
  83. } // namespace atomics
  84. } // namespace boost
  85. #include <boost/atomic/detail/footer.hpp>
  86. #endif // BOOST_ATOMIC_THREAD_PAUSE_HPP_INCLUDED_