diff --git a/emper/Emper.hpp b/emper/Emper.hpp index 2beb9c0149d9ed8a067eea15a6622d3d1be9b0e3..c87e99100b7ddcd950f8920f4140285fb8b3dfbc 100644 --- a/emper/Emper.hpp +++ b/emper/Emper.hpp @@ -163,4 +163,15 @@ static const bool HAS_FS_PATH = #endif ; +enum class CompleterSchedParam { + unchanged, + normal, + nice_10, + nice_19, + idle, +}; + +static const CompleterSchedParam COMPLETER_SCHED_PARAM = + CompleterSchedParam::EMPER_IO_COMPLETER_SCHED_PARAM; + } // namespace emper diff --git a/emper/io/GlobalIoContext.cpp b/emper/io/GlobalIoContext.cpp index a561324791c92aabc9635efa7eedec96d96a85d9..a4f01718ba0f073ee41431e30b88597813fd331d 100644 --- a/emper/io/GlobalIoContext.cpp +++ b/emper/io/GlobalIoContext.cpp @@ -4,6 +4,7 @@ #include <liburing.h> #include <liburing/io_uring.h> +#include <sched.h> #include <unistd.h> #include <cassert> @@ -193,6 +194,34 @@ void GlobalIoContext::startCompleter() { if (unlikely(errno)) { DIE_MSG_ERRNO("Creating completer thread failed"); } + + int sched_priority = 0, sched_policy; + + switch (emper::COMPLETER_SCHED_PARAM) { + case CompleterSchedParam::unchanged: + return; + case CompleterSchedParam::normal: + sched_policy = SCHED_OTHER; + break; + case CompleterSchedParam::nice_10: + sched_policy = SCHED_OTHER; + sched_priority = 10; + break; + case CompleterSchedParam::nice_19: + sched_policy = SCHED_OTHER; + sched_priority = 19; + break; + case CompleterSchedParam::idle: + sched_policy = SCHED_IDLE; + break; + } + + const struct sched_param param = {sched_priority}; + errno = pthread_setschedparam(completer, sched_policy, ¶m); + + if (unlikely(errno)) { + DIE_MSG_ERRNO("Setting scheduler parameter on completer thread failed"); + } } void GlobalIoContext::initiateTermination() { diff --git a/iwyu-mappings.imp b/iwyu-mappings.imp index f082c29c494cf2f276e2aa3e2f5e8959353e008c..34019d64c63bb35e2178ce15519a1b194789670d 100644 --- a/iwyu-mappings.imp +++ b/iwyu-mappings.imp @@ -5,6 +5,7 @@ { include: ["<bits/cxxabi_forced.h>", "private", "<ctime>", "public" ] }, { include: ["<bits/this_thread_sleep.h>", "private", "<thread>", "public" ] }, { include: ["<ext/alloc_traits.h>", "private", "<memory>", "public" ] }, + { include: ["<bits/types/struct_sched_param.h>", "private", "<sched.h>", "public" ] }, { symbol: ["__kernel_timespec", "private", "<liburing.h>", "public" ] }, { symbol: ["std::filesystem", "private", "<filesystem>", "public" ] }, diff --git a/meson.build b/meson.build index 056dd7c75cec49ad07b3f1ff7f15bd55a6eb0ba4..e31d9d4d80b7c26b27f7727c761bbe286e973fde 100644 --- a/meson.build +++ b/meson.build @@ -42,6 +42,7 @@ conf_data.set('EMPER_STATS', get_option('stats')) conf_data.set('EMPER_OVERFLOW_QUEUE', get_option('overflow_queue')) conf_data.set('EMPER_BLOCKED_CONTEXT_SET', get_option('blocked_context_set')) conf_data.set('EMPER_SET_AFFINITY_ON_BLOCK', get_option('set_affinity_on_block')) +conf_data.set('EMPER_IO_COMPLETER_SCHED_PARAM', get_option('io_completer_sched_param')) semaphore_impl = get_option('wakeup_semaphore_implementation') conf_data.set('EMPER_' + semaphore_impl.to_upper() + '_WAKEUP_SEMAPHORE', true) diff --git a/meson_options.txt b/meson_options.txt index 899b30b6ae540d8cc9c1d79eefc357889080524f..1cd5d81a4e618501181c035e1aa16bb62dc183db 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -160,3 +160,10 @@ option( value: false, description: 'Set the affinity when blocking', ) +option( + 'io_completer_sched_param', + type: 'combo', + description: 'The scheduling parmaters used for the completer thread', + choices: ['unchanged', 'normal', 'nice_10', 'nice_19', 'idle'], + value: 'unchanged', +)