diff --git a/core/reactor.cc b/core/reactor.cc index ec0e603ea61..46cce7794df 100644 --- a/core/reactor.cc +++ b/core/reactor.cc @@ -1667,14 +1667,31 @@ class reactor::lowres_timer_pollfn final : public reactor::pollfn { class reactor::smp_pollfn final : public reactor::pollfn { reactor& _r; + struct aligned_flag { + std::atomic flag; + char pad[63]; + bool try_lock() { + return !flag.exchange(true, std::memory_order_relaxed); + } + void unlock() { + flag.store(false, std::memory_order_relaxed); + } + }; + static aligned_flag _membarrier_lock; public: smp_pollfn(reactor& r) : _r(r) {} virtual bool poll() final override { return smp::poll_queues(); } virtual bool try_enter_interrupt_mode() override { + // systemwide_memory_barrier() is very slow if run concurrently, + // so don't go to sleep if it is running now. + if (!_membarrier_lock.try_lock()) { + return false; + } _r._sleeping.store(true, std::memory_order_relaxed); systemwide_memory_barrier(); + _membarrier_lock.unlock(); if (poll()) { // raced _r._sleeping.store(false, std::memory_order_relaxed); @@ -1687,6 +1704,8 @@ class reactor::smp_pollfn final : public reactor::pollfn { } }; +alignas(64) reactor::smp_pollfn::aligned_flag reactor::smp_pollfn::_membarrier_lock; + class reactor::epoll_pollfn final : public reactor::pollfn { reactor& _r; public: