diff --git a/emper/Dispatcher.cpp b/emper/Dispatcher.cpp index 0bef0cc50eb8ac37a53e42e9528cac5689749684..0cc1fb33c7cdfb87d5aa5d942d04b64ff2c2e171 100644 --- a/emper/Dispatcher.cpp +++ b/emper/Dispatcher.cpp @@ -2,6 +2,9 @@ // Copyright © 2020 Florian Schmaus #include "Dispatcher.hpp" +#include <pthread.h> // for pthread_yield + +#include "Emper.hpp" #include "Runtime.hpp" // for Runtime thread_local const Fiber* Dispatcher::currentFiber; @@ -11,3 +14,11 @@ auto Dispatcher::getDispatchLoop() -> func_t { } void Dispatcher::putRuntimeWorkerToSleep() { runtime.dispatcherLoopSleep(); } + +void Dispatcher::dispatchLoopDoSleep() { + if constexpr (emper::WORKER_SLEEP) { + putRuntimeWorkerToSleep(); + } else { + pthread_yield(); + } +} diff --git a/emper/Dispatcher.hpp b/emper/Dispatcher.hpp index 2a181fb53ff903a5cafe26059580b011f4c70e33..aeccd68e9433e87b93ae876bc81623fbe72fa281 100644 --- a/emper/Dispatcher.hpp +++ b/emper/Dispatcher.hpp @@ -19,6 +19,8 @@ class Dispatcher : public Logger<LogSubsystem::DISP> { Runtime& runtime; + void dispatchLoopDoSleep(); + virtual void dispatchLoop() = 0; auto getDispatchLoop() -> func_t; diff --git a/emper/Emper.hpp b/emper/Emper.hpp new file mode 100644 index 0000000000000000000000000000000000000000..76fa35e31ccb4ed0defe0e1511cba81f1b05e5d1 --- /dev/null +++ b/emper/Emper.hpp @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright © 2020 Florian Schmaus +#pragma once + +#include <emper-config.h> + +namespace emper { + +static const bool STATS = +#ifdef EMPER_STATS + true +#else + false +#endif + ; + +static const bool WORKER_SLEEP = +#ifdef EMPER_WORKER_SLEEP + true +#else + false +#endif + ; + +} // namespace emper diff --git a/emper/Runtime.cpp b/emper/Runtime.cpp index b413c74256efb132fa50c5e23ecf9e2ae4b8f0b6..48f1a8b96978f1cd8f1fcb5c5b568ebd47d1a349 100644 --- a/emper/Runtime.cpp +++ b/emper/Runtime.cpp @@ -12,10 +12,11 @@ #include <cstdlib> // for rand, srand, abort #include <memory> // for __shared_ptr_access, shared_ptr -#include "Common.hpp" // for DIE_MSG_ERRNO, DIE, DIE_MSG -#include "ContextManager.hpp" // for ContextManager -#include "Debug.hpp" // for DBG, ABORT, LOGD, LOGE -#include "Dispatcher.hpp" // for Dispatcher +#include "Common.hpp" // for DIE_MSG_ERRNO, DIE, DIE_MSG +#include "ContextManager.hpp" // for ContextManager +#include "Debug.hpp" // for DBG, ABORT, LOGD, LOGE +#include "Dispatcher.hpp" // for Dispatcher +#include "Emper.hpp" #include "Fiber.hpp" // for Fiber #include "RuntimeStrategy.hpp" // for RuntimeStrategy #include "RuntimeStrategyStats.hpp" // for RuntimeStrategyStats @@ -80,12 +81,12 @@ Runtime::Runtime(workerid_t workerCount, RuntimeStrategy& strategy, unsigned int if (errno) DIE_MSG_ERRNO("pthread_create() failed"); } -#ifdef EMPER_STATS - int res = std::atexit(&printLastRuntimeStats); - if (res) { - DIE_MSG("could not register printStats() with at_exit()"); + if constexpr (emper::STATS) { + int res = std::atexit(&printLastRuntimeStats); + if (res) { + DIE_MSG("could not register printStats() with at_exit()"); + } } -#endif } Runtime::~Runtime() { diff --git a/emper/strategies/laws/LawsDispatcher.cpp b/emper/strategies/laws/LawsDispatcher.cpp index a935e55bdd11bf6a76fc38fa3d85553c2795a3a1..04bfbde1be06b7b5c9c19e54abd2fe7c812f1f10 100644 --- a/emper/strategies/laws/LawsDispatcher.cpp +++ b/emper/strategies/laws/LawsDispatcher.cpp @@ -2,21 +2,20 @@ // Copyright © 2020 Florian Schmaus #include "LawsDispatcher.hpp" -#include "LawsStrategy.hpp" // IWYU pragma: keep -#include "Runtime.hpp" -#include "emper-config.h" +#include <atomic> // for atomic, memory_order_relaxed -class Fiber; +#include "Common.hpp" // for DIE_MSG +#include "Emper.hpp" +#include "Fiber.hpp" // for Fiber +#include "LawsStrategy.hpp" // for LawsStrategy, LawsStrategy::FiberSource +#include "Runtime.hpp" void LawsDispatcher::dispatchLoop() { while (true) { Fiber* const fiber = runtime.nextFiber(); if (!fiber) { -#ifdef EMPER_WORKER_SLEEP - putRuntimeWorkerToSleep(); -#else - pthread_yield(); -#endif + dispatchLoopDoSleep(); + continue; } @@ -24,27 +23,27 @@ void LawsDispatcher::dispatchLoop() { // boolean initialize to true in order to check if this fiber // is runnable. if (isRunnable(fiber)) { -#ifdef EMPER_STATS - LawsStrategy::FiberSource fiberSource = - static_cast<LawsStrategy::FiberSource>(fiber->getFlag()); - switch (fiberSource) { - case LawsStrategy::FiberSource::fromPriority: - lawsStrategy.dispatchedFiberFromPriority.fetch_add(1, std::memory_order_relaxed); - break; - case LawsStrategy::FiberSource::fromLocal: - lawsStrategy.dispatchedFiberFromLocal.fetch_add(1, std::memory_order_relaxed); - break; - case LawsStrategy::FiberSource::stolen: - lawsStrategy.dispatchedFiberStolen.fetch_add(1, std::memory_order_relaxed); - break; - case LawsStrategy::FiberSource::mainThread: - lawsStrategy.dispatchedFiberFromMainThread.fetch_add(1, std::memory_order_relaxed); - break; - default: - DIE_MSG("Unknown fiber flag: " << flag); - break; + if constexpr (emper::STATS) { + auto fiberSource = static_cast<LawsStrategy::FiberSource>(fiber->getFlag()); + switch (fiberSource) { + case LawsStrategy::FiberSource::fromPriority: + lawsStrategy.dispatchedFiberFromPriority.fetch_add(1, std::memory_order_relaxed); + break; + case LawsStrategy::FiberSource::fromLocal: + lawsStrategy.dispatchedFiberFromLocal.fetch_add(1, std::memory_order_relaxed); + break; + case LawsStrategy::FiberSource::stolen: + lawsStrategy.dispatchedFiberStolen.fetch_add(1, std::memory_order_relaxed); + break; + case LawsStrategy::FiberSource::mainThread: + lawsStrategy.dispatchedFiberFromMainThread.fetch_add(1, std::memory_order_relaxed); + break; + default: + DIE_MSG("Unknown fiber flag: " << flag); + break; + } } -#endif + // The fiber was marked das runnable. Run it now. dispatch(fiber); // Update the affinity if one was set. diff --git a/emper/strategies/laws/LawsScheduler.cpp b/emper/strategies/laws/LawsScheduler.cpp index 98031bc76c61ef1b51a4efe03335851270fc9867..2c867f1893d098c54277030868883a962c44a88d 100644 --- a/emper/strategies/laws/LawsScheduler.cpp +++ b/emper/strategies/laws/LawsScheduler.cpp @@ -2,11 +2,13 @@ // Copyright © 2020 Florian Schmaus #include "LawsScheduler.hpp" +#include <atomic> // for atomic, memory_order_relaxed + #include "Common.hpp" #include "Debug.hpp" +#include "Emper.hpp" #include "LawsStrategy.hpp" // IWYU pragma: keep #include "Runtime.hpp" -#include "emper-config.h" #define EMPER_OVERFLOW_QUEUE @@ -47,9 +49,9 @@ void LawsScheduler::schedule(Fiber& fiber) { // We found a fiber to schedule on a remote prority queue. increaseRefCount(fiber); priorityQueues[affinity]->enqueue(&fiber); -#ifdef EMPER_STATS - lawsStrategy.scheduledFibersToRemotePriority.fetch_add(1, std::memory_order_relaxed); -#endif + if constexpr (emper::STATS) { + lawsStrategy.scheduledFibersToRemotePriority.fetch_add(1, std::memory_order_relaxed); + } } scheduleToLocalWsQueue: @@ -61,34 +63,36 @@ scheduleToLocalWsQueue: ABORT("Could not push fiber " << &fiber << " into queue"); #endif } else { -#ifdef EMPER_STATS - lawsStrategy.scheduledFibersToLocal.fetch_add(1, std::memory_order_relaxed); -#endif + if constexpr (emper::STATS) { + lawsStrategy.scheduledFibersToLocal.fetch_add(1, std::memory_order_relaxed); + } } -#ifdef EMPER_WORKER_SLEEP - notifyRuntimeAboutNewWork(); -#endif + if constexpr (emper::WORKER_SLEEP) { + notifyRuntimeAboutNewWork(); + } } auto LawsScheduler::nextFiber() -> Fiber* { Fiber* fiber = priorityQueue.dequeue(); if (fiber != nullptr) { // We fetched a fiber from your local priority queue. -#ifdef EMPER_STATS - unsigned int flag = static_cast<unsigned int>(LawsStrategy::FiberSource::fromPriority); - fiber->setFlag(flag); -#endif + if constexpr (emper::STATS) { + auto flag = static_cast<unsigned int>(LawsStrategy::FiberSource::fromPriority); + fiber->setFlag(flag); + } + return fiber; } bool poped = queue.popBottom(&fiber); if (likely(poped)) { -#ifdef EMPER_STATS - unsigned int flag = static_cast<unsigned int>(LawsStrategy::FiberSource::fromLocal); - fiber->setFlag(flag); -#endif + if constexpr (emper::STATS) { + auto flag = static_cast<unsigned int>(LawsStrategy::FiberSource::fromLocal); + fiber->setFlag(flag); + } + return fiber; } @@ -100,10 +104,11 @@ auto LawsScheduler::nextFiber() -> Fiber* { poped = queues[victim]->popTop(&fiber); if (poped) { -#ifdef EMPER_STATS - unsigned int flag = static_cast<unsigned int>(LawsStrategy::FiberSource::stolen); - fiber->setFlag(flag); -#endif + if (emper::STATS) { + auto flag = static_cast<unsigned int>(LawsStrategy::FiberSource::stolen); + fiber->setFlag(flag); + } + return fiber; } @@ -112,10 +117,11 @@ auto LawsScheduler::nextFiber() -> Fiber* { // Try the main thread queue to get work as last resort. poped = mainThreadQueue->popTop(&fiber); if (poped) { -#ifdef EMPER_STATS - unsigned int flag = static_cast<unsigned int>(LawsStrategy::FiberSource::mainThread); - fiber->setFlag(flag); -#endif + if constexpr (emper::STATS) { + auto flag = static_cast<unsigned int>(LawsStrategy::FiberSource::mainThread); + fiber->setFlag(flag); + } + return fiber; } diff --git a/emper/strategies/ws/WsDispatcher.cpp b/emper/strategies/ws/WsDispatcher.cpp index 14202e7bce39766a4aec7abb1d111fbcb42cadde..9e3394acd2c5ab66bd3bb8511bde2a16989d9fdc 100644 --- a/emper/strategies/ws/WsDispatcher.cpp +++ b/emper/strategies/ws/WsDispatcher.cpp @@ -2,8 +2,7 @@ // Copyright © 2020 Florian Schmaus #include "WsDispatcher.hpp" -#include "Runtime.hpp" // for Runtime -#include "emper-config.h" // for EMPER_WORKER_SLEEP +#include "Runtime.hpp" // for Runtime class Fiber; @@ -11,11 +10,8 @@ void WsDispatcher::dispatchLoop() { while (true) { const Fiber* fiber = runtime.nextFiber(); if (!fiber) { -#ifdef EMPER_WORKER_SLEEP - putRuntimeWorkerToSleep(); -#else - pthread_yield(); -#endif + dispatchLoopDoSleep(); + continue; } diff --git a/emper/strategies/ws/WsScheduler.cpp b/emper/strategies/ws/WsScheduler.cpp index a64f50107cb513777b616c7ffb983be67151b1f4..6b081a264be5d768b49cf92ed3623b22a73e1c22 100644 --- a/emper/strategies/ws/WsScheduler.cpp +++ b/emper/strategies/ws/WsScheduler.cpp @@ -2,12 +2,14 @@ // Copyright © 2020 Florian Schmaus #include "WsScheduler.hpp" +#include <atomic> #include <ostream> #include "Common.hpp" #include "Debug.hpp" +#include "Emper.hpp" #include "Runtime.hpp" -#include "emper-config.h" +#include "strategies/ws/WsStrategy.hpp" class Fiber; @@ -35,13 +37,13 @@ void WsScheduler::schedule(Fiber& fiber) { ABORT("Could not push fiber " << &fiber << " into queue"); } -#ifdef EMPER_STATS - wsStrategy.scheduledFibers.fetch_add(1, std::memory_order_relaxed); -#endif + if constexpr (emper::STATS) { + wsStrategy.scheduledFibers.fetch_add(1, std::memory_order_relaxed); + } -#ifdef EMPER_WORKER_SLEEP - notifyRuntimeAboutNewWork(); -#endif + if constexpr (emper::WORKER_SLEEP) { + notifyRuntimeAboutNewWork(); + } } auto WsScheduler::nextFiber() -> Fiber* { @@ -49,9 +51,9 @@ auto WsScheduler::nextFiber() -> Fiber* { bool poped = queue.popBottom(&fiber); if (likely(poped)) { -#ifdef EMPER_STATS - wsStrategy.nextFiberFromLocal.fetch_add(1, std::memory_order_relaxed); -#endif + if constexpr (emper::STATS) { + wsStrategy.nextFiberFromLocal.fetch_add(1, std::memory_order_relaxed); + } return fiber; } @@ -66,9 +68,10 @@ auto WsScheduler::nextFiber() -> Fiber* { poped = queues[victim]->popTop(&fiber); if (poped) { -#ifdef EMPER_STATS - wsStrategy.nextFiberStolen.fetch_add(1, std::memory_order_relaxed); -#endif + if constexpr (emper::STATS) { + wsStrategy.nextFiberStolen.fetch_add(1, std::memory_order_relaxed); + } + return fiber; } }