diff --git a/emper/Emper.cpp b/emper/Emper.cpp index 2c1c779e9f25216a3ad37e98a8abe16650d71159..c9f6be84169409faf91499385fb6cc53c1d8fabd 100644 --- a/emper/Emper.cpp +++ b/emper/Emper.cpp @@ -15,6 +15,7 @@ #include "emper-version.h" #include "emper.hpp" #include "io/Future.hpp" +#include "lib/LinuxVersion.hpp" void async(Fiber* fiber) { assert(fiber != nullptr); @@ -44,6 +45,8 @@ void async(const Fiber::fiber_fun0_t& function, workeraffinity_t* affinity) { namespace emper { +bool IO_MUST_INVALIDATE_BROKEN_CHAIN = EMPER_LINUX_LT("5.15.0"); + auto getFullVersion() -> std::string { return EMPER_FULL_VERSION; } static void ensure_no_current_runtime() { diff --git a/emper/Emper.hpp b/emper/Emper.hpp index c87e99100b7ddcd950f8920f4140285fb8b3dfbc..78736f3c93835e51010025719b5c885a48f6ba6b 100644 --- a/emper/Emper.hpp +++ b/emper/Emper.hpp @@ -130,6 +130,16 @@ static const bool IO_URING_SQPOLL = #endif ; +// Initialize this bool in Emper.cpp because it needs code evaluation +// (LinuxVersion::compare) during runtime. +// Using a static variable here means EACH object file including this header has to +// evaluate the needed code during library initialization. +// An extern variable results in a single execution during initialization of the +// Emper.cpp object. +// This also has the advantage that the probability we crash because printing +// warnings during the comparison use not yet initialized components is reduced. +extern bool IO_MUST_INVALIDATE_BROKEN_CHAIN; + static const bool IO_URING_SHARED_WQ = #ifdef EMPER_IO_URING_SHARED_WQ true diff --git a/emper/io/IoContext.cpp b/emper/io/IoContext.cpp index bfd680a340fed2d5e50be02da4583970dd66910c..6a867a05893fed7fecd757acee78caf17a7b2c18 100644 --- a/emper/io/IoContext.cpp +++ b/emper/io/IoContext.cpp @@ -197,7 +197,14 @@ void IoContext::submitAndWait(Future &future, unsigned wait_nr) { // broken chains. This means that all sqes in a chain except the broken one will // result in cqes with result -ECANCELD and the invalid one will // generate a cqe with the appropriate error code - if (unlikely(static_cast<unsigned>(submitted) < prepared)) { + + // When 5.15 is released with + // https://lore.kernel.org/io-uring/180ec124-79b1-2274-4570-9b0d6620d512@linux.alibaba.com/T/#t + // the kernel will consume the whole broken chain and we + // don't need to manually invalidate not submitted sqes. + // This allows SQPOLL to work for invalid chains. + if (unlikely(static_cast<unsigned>(submitted) < prepared) && + emper::IO_MUST_INVALIDATE_BROKEN_CHAIN) { cancelUnsubmittedChainParts<callerEnvironment>(future); }