From 2abd53e040171d8e9413d28e63312151f388efe6 Mon Sep 17 00:00:00 2001
From: Florian Fischer <florian.fischer@muhq.space>
Date: Thu, 2 Dec 2021 18:17:35 +0100
Subject: [PATCH] load CQ->tail only once during lockless stealing

Currently we load the CQ->tail with acquire semantic to determine
if we should steal from teh victim and load it again in the actual
stealing logic which will also immediately abort if there are no
CQEs to steal.

Keep the optimization for the locked case.
---
 emper/io/IoContext.hpp                             |  6 ++++++
 emper/strategies/AbstractWorkStealingScheduler.cpp | 10 ++++------
 2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/emper/io/IoContext.hpp b/emper/io/IoContext.hpp
index 60b1e99a..b8aa5b9c 100644
--- a/emper/io/IoContext.hpp
+++ b/emper/io/IoContext.hpp
@@ -413,6 +413,12 @@ class IoContext : public Logger<LogSubsystem::IO> {
 			return reapCompletionsLockless<callerEnvironment>(continuations, toReap);
 		}
 
+		// CallerEnvironment::EMPER means we are in a stealing worker.
+		// Check if the victim's CQ is empty before taking the lock.
+		if constexpr (callerEnvironment == CallerEnvironment::EMPER) {
+			if (!cqeCount()) return 0;
+		}
+
 		return reapCompletionsLocked<callerEnvironment>(continuations, toReap);
 	}
 
diff --git a/emper/strategies/AbstractWorkStealingScheduler.cpp b/emper/strategies/AbstractWorkStealingScheduler.cpp
index 83ca8769..5f20567f 100644
--- a/emper/strategies/AbstractWorkStealingScheduler.cpp
+++ b/emper/strategies/AbstractWorkStealingScheduler.cpp
@@ -139,12 +139,10 @@ popTop:
 
 	if constexpr (emper::IO_STEALING) {
 		auto* victimIo = runtime.ioContexts[victim];
-		if (victimIo->cqeCount()) {
-			fiber = victimIo->reapSingleCompletion<CallerEnvironment::EMPER>();
-			if (fiber) {
-				emper::statsIncr(awss::stats.nextIoFiberStolen);
-				return std::make_pair(fiber, FiberSource::ioStolen);
-			}
+		fiber = victimIo->reapSingleCompletion<CallerEnvironment::EMPER>();
+		if (fiber) {
+			emper::statsIncr(awss::stats.nextIoFiberStolen);
+			return std::make_pair(fiber, FiberSource::ioStolen);
 		}
 	}
 
-- 
GitLab