spin_wait.cpp 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. #include "spin_wait.h"
  2. #include <util/datetime/base.h>
  3. #include <util/system/compiler.h>
  4. #include <atomic>
  5. namespace NYT::NThreading {
  6. ////////////////////////////////////////////////////////////////////////////////
  7. static constexpr int SpinIterationCount = 1000;
  8. namespace {
  9. TDuration SuggestSleepDelay(int iteration)
  10. {
  11. static std::atomic<ui64> Rand;
  12. auto rand = Rand.load(std::memory_order::relaxed);
  13. rand = 0x5deece66dLL * rand + 0xb; // numbers from nrand48()
  14. Rand.store(rand, std::memory_order::relaxed);
  15. constexpr ui64 MinDelayUs = 128;
  16. // Double delay every 8 iterations, up to 16x (2ms).
  17. if (iteration > 32) {
  18. iteration = 32;
  19. }
  20. ui64 delayUs = MinDelayUs << (iteration / 8);
  21. // Randomize in delay..2*delay range, for resulting 128us..4ms range.
  22. delayUs = delayUs | ((delayUs - 1) & rand);
  23. return TDuration::MicroSeconds(delayUs);
  24. }
  25. } // namespace
  26. ////////////////////////////////////////////////////////////////////////////////
  27. TSpinWait::TSpinWait(
  28. const TSourceLocation& location,
  29. ESpinLockActivityKind activityKind)
  30. : Location_(location)
  31. , ActivityKind_(activityKind)
  32. { }
  33. TSpinWait::~TSpinWait()
  34. {
  35. if (SlowPathStartInstant_ >= 0) {
  36. auto cpuDelay = GetCpuInstant() - SlowPathStartInstant_;
  37. InvokeSpinWaitSlowPathHooks(cpuDelay, Location_, ActivityKind_);
  38. }
  39. }
  40. void TSpinWait::Wait()
  41. {
  42. if (Y_LIKELY(SpinIteration_++ < SpinIterationCount)) {
  43. return;
  44. }
  45. SpinIteration_ = 0;
  46. if (SlowPathStartInstant_ < 0) {
  47. SlowPathStartInstant_ = GetCpuInstant();
  48. }
  49. Sleep(SuggestSleepDelay(SleepIteration_++));
  50. }
  51. ////////////////////////////////////////////////////////////////////////////////
  52. } // namespace NYT::NThreading