diff --git a/emper/Common.hpp b/emper/Common.hpp index 4b10454c96f2fd7a00643113298562b9802f350e..9e3832eca10276a7bff8c88206da1723e508d4c9 100644 --- a/emper/Common.hpp +++ b/emper/Common.hpp @@ -30,7 +30,7 @@ using func_t = std::function<void()>; #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) -#define CACHE_LINE_SIZE 64 +#define CACHE_LINE_SIZE EMPER_ASSUME_CACHE_LINE_SIZE #define ALIGN_TO_CACHE_LINE alignas(CACHE_LINE_SIZE) #define CACHE_LINE_EXCLUSIVE(T, symbol) \ std::aligned_storage<CACHE_LINE_SIZE, CACHE_LINE_SIZE>::type __##symbol##_mem; \ diff --git a/emper/Context.hpp b/emper/Context.hpp index 0964ed67d228c417ca07e58ec470e69e5cc6237a..73f29e36ddf307126344d08a220997be87dcadd9 100644 --- a/emper/Context.hpp +++ b/emper/Context.hpp @@ -13,12 +13,16 @@ #include "Common.hpp" // for func_t, DIE, ALIGN_TO_CACHE_LINE #include "Debug.hpp" // for LOGD, LogSubsystem, LogSubsystem::C, Logger #include "Emper.hpp" // for Emper::DEBUG +#include "emper-config.h" +#include "lib/math.hpp" class AbstractFiber; class ContextManager; class Dispatcher; class Fibril; +namespace em = emper::lib::math; + extern "C" [[noreturn]] void switch_and_load_context(void** toTos); // *Not* marked as 'noreturn' because save_and_switch_context does // *actually return at some point, unlike the other switch_* @@ -26,9 +30,10 @@ extern "C" [[noreturn]] void switch_and_load_context(void** toTos); extern "C" void save_and_switch_context(void** toTos, void** fromTos); extern "C" [[noreturn]] void switch_context(void** toTos); -class ALIGN_TO_CACHE_LINE Context : Logger<LogSubsystem::C> { +class EMPER_CONTEXT_ALIGNAS Context : Logger<LogSubsystem::C> { private: - static const unsigned int CONTEXT_SIZE = 0xffff; // 1024 * 1024 * 4; + static constexpr size_t CONTEXT_SIZE = + em::roundUp(emper::MIN_CONTEXT_STACK_SIZE, emper::ASSUME_PAGE_SIZE); static thread_local Context* currentContext; @@ -45,10 +50,8 @@ class ALIGN_TO_CACHE_LINE Context : Logger<LogSubsystem::C> { func_t startAndResumeHook; - // Allign the stack to a cache line, so that it isn't shared with - // the other members of this class. // NOLINTNEXTLINE(modernize-avoid-c-arrays) - ALIGN_TO_CACHE_LINE char context[CONTEXT_SIZE]; + char context[CONTEXT_SIZE]; void printTo(std::ostream& strm, bool withPtr = true) const; diff --git a/emper/Emper.hpp b/emper/Emper.hpp index 488b9bf89ee543139efd6889180823e4b92a260f..93df71cfd4e46ac04218fdadf54323985f1dfda8 100644 --- a/emper/Emper.hpp +++ b/emper/Emper.hpp @@ -278,4 +278,11 @@ static const bool CONTEXT_MANAGER_WITH_MEMORY_MANAGER = false #endif ; + +static const size_t ASSUME_PAGE_SIZE = EMPER_ASSUME_PAGE_SIZE; + +static const size_t MIN_CONTEXT_STACK_SIZE = EMPER_MIN_CONTEXT_STACK_SIZE; + +static const size_t ASSUME_CACHE_LINE_SIZE = EMPER_ASSUME_CACHE_LINE_SIZE; + } // namespace emper diff --git a/emper/lib/math.hpp b/emper/lib/math.hpp index 953d74450bb34974820a12f7bbd93d133cc5c857..a2e8e95b109b7f6548aa41f5a1201a7f397e7468 100644 --- a/emper/lib/math.hpp +++ b/emper/lib/math.hpp @@ -65,4 +65,8 @@ class RunningAverage { } }; +constexpr size_t roundUp(size_t number, size_t multiple) { + size_t multiple_count = (number + multiple - 1) / multiple; + return multiple_count * multiple; +} } // namespace emper::lib::math diff --git a/eval/SpawnALot.cpp b/eval/SpawnALot.cpp index 4aa6bb199adbb72f998b7861cb609822c49bd387..bc0b7749a14504ba5b5b04604d30e51ef0e82332 100644 --- a/eval/SpawnALot.cpp +++ b/eval/SpawnALot.cpp @@ -1,12 +1,13 @@ // SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright © 2020 Florian Schmaus +// Copyright © 2020-2022 Florian Schmaus #include <chrono> // for nanoseconds, time_point, dur... #include <cstdint> // for uint8_t, uint64_t #include <cstdlib> // for EXIT_SUCCESS #include <iostream> // for operator<<, basic_ostream #include <thread> // for thread -#include "BinaryPrivateSemaphore.hpp" // for BPS +#include "BinaryPrivateSemaphore.hpp" +#include "Common.hpp" #include "CountingPrivateSemaphore.hpp" // for CPS #include "Fiber.hpp" // for Fiber #include "PrivateSemaphore.hpp" // for PS @@ -14,8 +15,6 @@ #include "emper-common.h" // for UNUSED_ARG #include "lib/DebugUtil.hpp" // for enableStacktraceOnAborts -#define CACHE_LINE_SIZE 64 - static void spawnALotThreadsRecursiveTFun(unsigned int depth, unsigned int width, unsigned int current_depth) { if (current_depth == depth) return; diff --git a/meson.build b/meson.build index 91d72dd827ee5f3c8f043f61baf07046ac539b6d..dff49db29f40ed32ea2306d6afdd29a673e21075 100644 --- a/meson.build +++ b/meson.build @@ -54,6 +54,8 @@ endif continuation_stealing_mode = get_option('continuation_stealing_mode') locked_ws_queue = get_option('locked_ws_queue') +assume_page_size = get_option('assume_page_size') +assume_cache_line_size = get_option('assume_cache_line_size') conf_data.set('EMPER_WORKER_SLEEP', get_option('worker_sleep')) conf_data.set('EMPER_WORKER_WAKEUP_STRATEGY', get_option('worker_wakeup_strategy')) @@ -70,6 +72,21 @@ conf_data.set('EMPER_CONTINUATION_STEALING_MODE', continuation_stealing_mode) conf_data.set('EMPER_CONTINUATION_STEALING_MADVISE_STACK', get_option('continuation_stealing_madvise_stack')) conf_data.set('EMPER_BUILD_WITH_CLANG', cpp_is_clang) conf_data.set('EMPER_CONTEXT_MANAGER_WITH_MEMORY_MANAGER', get_option('context_manager_with_memory_manager')) +conf_data.set('EMPER_ASSUME_PAGE_SIZE', assume_page_size) +conf_data.set('EMPER_MIN_CONTEXT_STACK_SIZE', get_option('min_context_stack_size')) +conf_data.set('EMPER_ASSUME_CACHE_LINE_SIZE', assume_cache_line_size) + +context_alignment = get_option('context_alignment') +if context_alignment == 'none' + context_alignas = '' +elif context_alignment == 'cache_line_size' + context_alignas = 'alignas(' + cache_line_size + ')' +elif context_alignment == 'page_size' + context_alignas = 'alignas(' + page_size + ')' +else + error('Unknown context alignment option: ' + context_alignment) +endif +conf_data.set('EMPER_CONTEXT_ALIGNAS', context_alignas) if continuation_stealing_mode == 'locked' and not locked_ws_queue error('*Locked* continuation stealing only works with locked work-stealing queues (locked_ws_queue=true)') diff --git a/meson_options.txt b/meson_options.txt index 0f7cabd9fad62c0b051124db9a9f0d7a79dfd6c9..df0459d002b4125e9a312c4986d34b6c64e18b2a 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -237,3 +237,31 @@ option( description: 'Use the memory manager in context manager for better context caching. This may increases the memory footprint', value: true ) +option( + 'assume_page_size', + type: 'integer', + description: 'Assume the given page size in bytes', + value: 4096, + min: 1, +) +option( + 'min_context_stack_size', + type: 'integer', + description: 'Set the size in bytes of stacks used by an execution context (will potentially be rounded up to the next page size)', + value: 65536, + min: 1, +) +option( + 'context_alignment', + type: 'combo', + description: 'Use the select mechanism to determine the alignment of contexts', + choices: ['none', 'cache_line_size', 'page_size'], + value: 'none', +) +option( + 'assume_cache_line_size', + type: 'integer', + description: 'Assume the given cache-line size in bytes', + value: 64, + min: 1, +)