From 074a7157b6bd3867b60d04f685cdede6063e6e3c Mon Sep 17 00:00:00 2001 From: Benoit Germain Date: Wed, 7 May 2025 15:43:01 +0200 Subject: Thread priority rework * thread priorities can now be set using the native range of values, if desired. * thread API errors cause a Lua error instead of aborting the program. * new function lanes.thread_priority_range(), to query the valid range of priorities. * unit tests for all of the above --- src/lane.cpp | 4 +- src/lane.hpp | 2 +- src/lanes.cpp | 62 +++++++++++++++-------- src/lanes.lua | 42 +++++++++++----- src/threading.cpp | 146 ++++++++++++++++++++++++++++++++---------------------- src/threading.hpp | 14 ++++-- src/universe.hpp | 5 +- 7 files changed, 175 insertions(+), 100 deletions(-) (limited to 'src') diff --git a/src/lane.cpp b/src/lane.cpp index 26ddebd..65a776e 100644 --- a/src/lane.cpp +++ b/src/lane.cpp @@ -1169,11 +1169,11 @@ void Lane::securizeDebugName(lua_State* const L_) // ################################################################################################# -void Lane::startThread(int const priority_) +void Lane::startThread(lua_State* const L_, int const priority_, NativePrioFlag native_) { thread = std::thread([this]() { lane_main(this); }); if (priority_ != kThreadPrioDefault) { - THREAD_SET_PRIORITY(thread, priority_, U->sudo); + THREAD_SET_PRIORITY(L_, thread, priority_, native_, U->sudo); } } diff --git a/src/lane.hpp b/src/lane.hpp index 5fe36b6..917606f 100644 --- a/src/lane.hpp +++ b/src/lane.hpp @@ -204,7 +204,7 @@ class Lane final [[nodiscard]] bool selfdestructRemove(); void securizeDebugName(lua_State* L_); - void startThread(int priority_); + void startThread(lua_State* L_, int priority_, NativePrioFlag native_); void storeDebugName( std::string_view const& name_); [[nodiscard]] int storeResults(lua_State* L_); diff --git a/src/lanes.cpp b/src/lanes.cpp index d1a353b..0eaeb3e 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp @@ -137,13 +137,15 @@ LUAG_FUNC(set_singlethreaded) LUAG_FUNC(set_thread_priority) { lua_Integer const _prio{ luaL_checkinteger(L_, 1) }; + NativePrioFlag const _native{ std::string_view{ "native" } == luaL_optstring(L_, 2, "mapped") }; // public Lanes API accepts a generic range -3/+3 // that will be remapped into the platform-specific scheduler priority scheme // On some platforms, -3 is equivalent to -2 and +3 to +2 - if (_prio < kThreadPrioMin || _prio > kThreadPrioMax) { + if (!_native && (_prio < kThreadPrioMin || _prio > kThreadPrioMax)) { raise_luaL_error(L_, "priority out of range: %d..+%d (%d)", kThreadPrioMin, kThreadPrioMax, _prio); } - THREAD_SET_PRIORITY(static_cast(_prio), Universe::Get(L_)->sudo); + + THREAD_SET_PRIORITY(L_, static_cast(_prio), _native, Universe::Get(L_)->sudo); return 0; } @@ -155,7 +157,8 @@ LUAG_FUNC(set_thread_affinity) if (_affinity <= 0) { raise_luaL_error(L_, "invalid affinity (%d)", _affinity); } - THREAD_SET_AFFINITY(static_cast(_affinity)); + + THREAD_SET_AFFINITY(L_, static_cast(_affinity)); return 0; } @@ -236,9 +239,26 @@ int lanes_register(lua_State* const L_) // ################################################################################################# +LUAG_FUNC(thread_priority_range) +{ + NativePrioFlag const _native{ std::string_view{ "native" } == luaL_optstring(L_, 1, "mapped") }; + if (_native) { + auto const [_prio_min, _prio_max] = THREAD_NATIVE_PRIOS(); + lua_pushinteger(L_, _prio_min); + lua_pushinteger(L_, _prio_max); + } else { + lua_pushinteger(L_, kThreadPrioMin); + lua_pushinteger(L_, kThreadPrioMax); + } + return 2; +} + +// ################################################################################################# + //--- [] means can be nil // lane_ud = lane_new( function // , [libs_str] +// , [prio_is_native_bool] // , [priority_int] // , [globals_tbl] // , [package_tbl] @@ -255,15 +275,16 @@ LUAG_FUNC(lane_new) { static constexpr StackIndex kFuncIdx{ 1 }; static constexpr StackIndex kLibsIdx{ 2 }; - static constexpr StackIndex kPrioIdx{ 3 }; - static constexpr StackIndex kGlobIdx{ 4 }; - static constexpr StackIndex kPackIdx{ 5 }; - static constexpr StackIndex kRequIdx{ 6 }; - static constexpr StackIndex kGcCbIdx{ 7 }; - static constexpr StackIndex kNameIdx{ 8 }; - static constexpr StackIndex kErTlIdx{ 9 }; - static constexpr StackIndex kAsCoro{ 10 }; - static constexpr StackIndex kFixedArgsIdx{ 10 }; + static constexpr StackIndex kPrinIdx{ 3 }; + static constexpr StackIndex kPrioIdx{ 4 }; + static constexpr StackIndex kGlobIdx{ 5 }; + static constexpr StackIndex kPackIdx{ 6 }; + static constexpr StackIndex kRequIdx{ 7 }; + static constexpr StackIndex kGcCbIdx{ 8 }; + static constexpr StackIndex kNameIdx{ 9 }; + static constexpr StackIndex kErTlIdx{ 10 }; + static constexpr StackIndex kAsCoro{ 11 }; + static constexpr StackIndex kFixedArgsIdx{ 11 }; int const _nargs{ lua_gettop(L_) - kFixedArgsIdx }; LUA_ASSERT(L_, _nargs >= 0); @@ -400,21 +421,22 @@ LUAG_FUNC(lane_new) // public Lanes API accepts a generic range -3/+3 // that will be remapped into the platform-specific scheduler priority scheme // On some platforms, -3 is equivalent to -2 and +3 to +2 - int const _priority{ + auto const [_priority, _native] { std::invoke([L = L_]() { + NativePrioFlag const _native{ static_cast(lua_toboolean(L, kPrinIdx)) }; StackIndex const _prio_idx{ lua_isnoneornil(L, kPrioIdx) ? kIdxNone : kPrioIdx }; - if (_prio_idx == 0) { - return kThreadPrioDefault; + if (_prio_idx == kIdxNone) { + return std::make_pair(kThreadPrioDefault, _native); } int const _priority{ static_cast(lua_tointeger(L, _prio_idx)) }; - if ((_priority < kThreadPrioMin || _priority > kThreadPrioMax)) { + if (!_native && (_priority < kThreadPrioMin || _priority > kThreadPrioMax)) { raise_luaL_error(L, "Priority out of range: %d..+%d (%d)", kThreadPrioMin, kThreadPrioMax, _priority); } - return _priority; + return std::make_pair(_priority, _native); }) }; - _lane->startThread(_priority); + _lane->startThread(L_, _priority, _native); STACK_GROW(_L2, _nargs + 3); STACK_GROW(L_, 3); @@ -658,6 +680,7 @@ namespace { { Universe::kFinally, Universe::InitializeFinalizer }, { "linda", LG_linda }, { "nameof", LG_nameof }, + { "thread_priority_range", LG_thread_priority_range }, { "now_secs", LG_now_secs }, { "register", lanes_register }, { "set_singlethreaded", LG_set_singlethreaded }, @@ -753,9 +776,6 @@ LUAG_FUNC(configure) ); // L_: settings M VERSION lua_setfield(L_, -2, "version"); // L_: settings M - lua_pushinteger(L_, kThreadPrioMax); // L_: settings M kThreadPrioMax - lua_setfield(L_, -2, "max_prio"); // L_: settings M - kCancelError.pushKey(L_); // L_: settings M kCancelError lua_setfield(L_, -2, "cancel_error"); // L_: settings M diff --git a/src/lanes.lua b/src/lanes.lua index 3ee959c..c5b3315 100644 --- a/src/lanes.lua +++ b/src/lanes.lua @@ -280,6 +280,10 @@ local opt_validators = local tv = type(v_) return (tv == "string") and v_ or raise_option_error("name", tv, v_) end, + native_priority = function(v_) + local tv = type(v_) + return (tv == "number") and v_ or raise_option_error("native_priority", tv, v_) + end, package = function(v_) local tv = type(v_) return (tv == "table") and v_ or raise_option_error("package", tv, v_) @@ -295,7 +299,7 @@ local opt_validators = } -- ############################################################################################# --- ##################################### lanes.gen() ########################################### +-- ################################### lanes.gen/coro() ######################################## -- ############################################################################################# local process_gen_opt = function(...) @@ -367,9 +371,16 @@ local process_gen_opt = function(...) opt[k] = validator(v) end end + + -- special case: can't have priority and native_priority at the same time + if opt.priority and opt.native_priority then + error "priority and native_priority cannot be specified together" + end return func, libs, opt end -- process_gen_opt +-- ################################################################################################# + -- lane_h[1..n]: lane results, same as via 'lane_h:join()' -- lane_h[0]: can be read to make sure a thread has finished (gives the number of available results) -- lane_h[negative]: error message, without propagating the error @@ -408,25 +419,28 @@ end -- process_gen_opt -- Calling with a function argument ('lane_func') ends the string/table -- modifiers, and prepares a lane generator. --- receives a sequence of strings and tables, plus a function -local gen = function(...) +local make_generator = function(is_coro_, ...) local func, libs, opt = process_gen_opt(...) local core_lane_new = assert(core.lane_new) - local priority, globals, package, required, gc_cb, name, error_trace_level = opt.priority, opt.globals, opt.package or package, opt.required, opt.gc_cb, opt.name, error_trace_levels[opt.error_trace_level] + local prio_is_native = opt.native_priority and true or false + local priority, globals, package, required, gc_cb, name, error_trace_level = opt.priority or opt.native_priority, opt.globals, opt.package or package, opt.required, opt.gc_cb, opt.name, error_trace_levels[opt.error_trace_level] return function(...) -- must pass functions args last else they will be truncated to the first one - return core_lane_new(func, libs, priority, globals, package, required, gc_cb, name, error_trace_level, false, ...) + return core_lane_new(func, libs, prio_is_native, priority, globals, package, required, gc_cb, name, error_trace_level, is_coro_, ...) end +end -- make_generator + +-- ################################################################################################# + +-- receives a sequence of strings and tables, plus a function +local gen = function(...) + return make_generator(false, ...) end -- gen() +-- ################################################################################################# + local coro = function(...) - local func, libs, opt = process_gen_opt(...) - local core_lane_new = assert(core.lane_new) - local priority, globals, package, required, gc_cb, name, error_trace_level = opt.priority, opt.globals, opt.package or package, opt.required, opt.gc_cb, opt.name, error_trace_levels[opt.error_trace_level] - return function(...) - -- must pass functions args last else they will be truncated to the first one - return core_lane_new(func, libs, priority, globals, package, required, gc_cb, name, error_trace_level, true, ...) - end + return make_generator(true, ...) end -- coro() -- ################################################################################################# @@ -656,7 +670,8 @@ local configure_timers = function() end end end -- timer_body() - timer_lane = gen("lanes_core,table", { name = "LanesTimer", package = {}, priority = core.max_prio }, timer_body)() + local min_prio, max_prio = core.thread_priority_range() + timer_lane = gen("lanes_core,table", { name = "LanesTimer", package = {}, priority = max_prio }, timer_body)() end -- first_time ----- @@ -876,6 +891,7 @@ local configure = function(settings_) lanes.set_thread_affinity = core.set_thread_affinity lanes.set_thread_priority = core.set_thread_priority lanes.sleep = core.sleep + lanes.thread_priority_range = core.thread_priority_range lanes.threads = core.threads or function() error "lane tracking is not available" end -- core.threads isn't registered if settings.track_lanes is false lanes.gen = gen diff --git a/src/threading.cpp b/src/threading.cpp index 483a228..efca7eb 100644 --- a/src/threading.cpp +++ b/src/threading.cpp @@ -49,6 +49,7 @@ THE SOFTWARE. #endif // __linux__ +#include "compat.hpp" #include "threading.hpp" #if !defined(PLATFORM_XBOX) && !defined(PLATFORM_WIN32) && !defined(PLATFORM_POCKETPC) @@ -82,25 +83,42 @@ THE SOFTWARE. #pragma warning(disable : 4054) #endif +static constexpr std::string_view StripFuncName(std::string_view const& where_) +{ + std::string_view funcname_{ where_ }; + + auto _args_pos{ funcname_.find_first_of('(') }; + funcname_ = funcname_.substr(0, _args_pos); + auto _name_pos{ funcname_.find_last_of(' ') }; + funcname_.remove_prefix(_name_pos + 1); + return funcname_; +} + /* * FAIL is for unexpected API return values - essentially programming * error in _this_ code. */ #if HAVE_WIN32 -static void FAIL(char const* funcname_, DWORD const rc_) + +template +void Win32Invoke(lua_State* const L_, std::string_view const& where_, F& f_, ARGS... args_) { + auto const _ret{ std::invoke(f_, std::forward(args_)...) }; + if (!_ret) { + auto const _rc{ GetLastError() }; + std::string_view const _funcname{ StripFuncName(where_) }; + #if defined(PLATFORM_XBOX) - fprintf(stderr, "%s() failed! (%d)\n", funcname_, rc_); -#else // PLATFORM_XBOX - char buf[256]; - FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, rc_, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, 256, nullptr); - fprintf(stderr, "%s() failed! [GetLastError() -> %lu] '%s'", funcname_, rc_, buf); + luaG_pushstring(L_, "%s() failed with code %d", _funcname.data(), _rc); +#else // PLATFORM_XBOX + char _buf[256]; + FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, _rc, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), _buf, 256, nullptr); + luaG_pushstring(L_, "%s() failed with code %d '%s'", _funcname.data(), _rc, _buf); #endif // PLATFORM_XBOX -#ifdef _MSC_VER - __debugbreak(); // give a chance to the debugger! -#endif // _MSC_VER - abort(); + raise_lua_error(L_); + } } + #endif // HAVE_WIN32 /*---=== Threading ===---*/ @@ -121,33 +139,35 @@ static int const gs_prio_remap[] = { // ################################################################################################# -void THREAD_SET_PRIORITY(int prio_, [[maybe_unused]] bool sudo_) +std::pair THREAD_NATIVE_PRIOS() { - // prio range [-3,+3] was checked by the caller - if (!SetThreadPriority(GetCurrentThread(), gs_prio_remap[prio_ + 3])) { - FAIL("THREAD_SET_PRIORITY", GetLastError()); - } + return std::make_pair(THREAD_PRIORITY_IDLE, THREAD_PRIORITY_TIME_CRITICAL); } // ################################################################################################# -void THREAD_SET_PRIORITY(std::thread& thread_, int prio_, [[maybe_unused]] bool sudo_) +[[nodiscard]] +void THREAD_SET_PRIORITY(lua_State* const L_, int const prio_, NativePrioFlag const native_, [[maybe_unused]] SudoFlag const sudo_) { - // prio range [-3,+3] was checked by the caller - // for some reason when building for mingw, native_handle() is an unsigned long long, but HANDLE is a void* - // -> need a strong cast to make g++ happy - if (!SetThreadPriority(thread_.native_handle(), gs_prio_remap[prio_ + 3])) { - FAIL("THREAD_SET_PRIORITY", GetLastError()); - } + // mapped prio range [-3,+3] was checked by the caller + return Win32Invoke(L_, std::source_location::current().function_name(), SetThreadPriority, GetCurrentThread(), native_ ? prio_ : gs_prio_remap[prio_ + 3]); } // ################################################################################################# -void THREAD_SET_AFFINITY(unsigned int aff_) +[[nodiscard]] +void THREAD_SET_PRIORITY(lua_State* const L_, std::thread& thread_, int const prio_, NativePrioFlag const native_, [[maybe_unused]] SudoFlag const sudo_) { - if (!SetThreadAffinityMask(GetCurrentThread(), aff_)) { - FAIL("THREAD_SET_AFFINITY", GetLastError()); - } + // mapped prio range [-3,+3] was checked by the caller + return Win32Invoke(L_, std::source_location::current().function_name(), SetThreadPriority, thread_.native_handle(), native_ ? prio_ : gs_prio_remap[prio_ + 3]); +} + +// ################################################################################################# + +[[nodiscard]] +void THREAD_SET_AFFINITY(lua_State* const L_, unsigned int aff_) +{ + return Win32Invoke(L_, std::source_location::current().function_name(), SetThreadAffinityMask, GetCurrentThread(), aff_); } // ################################################################################################# @@ -215,24 +235,24 @@ static int pthread_attr_setschedpolicy(pthread_attr_t* attr, int policy) #endif // pthread_attr_setschedpolicy() #endif // defined(__MINGW32__) || defined(__MINGW64__) -static void _PT_FAIL(int rc, const char* name, const char* file, int line) +template +void PthreadInvoke(lua_State* const L_, std::string_view const& where_, F& f_, ARGS... args_) { - const char* why = (rc == EINVAL) ? "EINVAL" - : (rc == EBUSY) ? "EBUSY" - : (rc == EPERM) ? "EPERM" - : (rc == ENOMEM) ? "ENOMEM" - : (rc == ESRCH) ? "ESRCH" - : (rc == ENOTSUP) ? "ENOTSUP" - : ""; - fprintf(stderr, "%s %d: %s failed, %d %s\n", file, line, name, rc, why); - abort(); -} -#define PT_CALL(call) \ - { \ - int rc = call; \ - if (rc != 0) \ - _PT_FAIL(rc, #call, __FILE__, __LINE__); \ + auto const _rc{ std::invoke(f_, std::forward(args_)...) }; + if (_rc) { + std::string_view const _funcname{ StripFuncName(where_) }; + + char const* _why = (_rc == EINVAL) ? "EINVAL" + : (_rc == EBUSY) ? "EBUSY" + : (_rc == EPERM) ? "EPERM" + : (_rc == ENOMEM) ? "ENOMEM" + : (_rc == ESRCH) ? "ESRCH" + : (_rc == ENOTSUP) ? "ENOTSUP" + : ""; + + raise_luaL_error(L_, "%s() failed with code %s", _funcname.data(), _why); } +} // array of 7 thread priority values, hand-tuned by platform so that we offer a uniform [-3,+3] public priority range static int const gs_prio_remap[] = { @@ -357,7 +377,18 @@ static int const gs_prio_remap[] = { #endif // _PRIO_0 }; -void THREAD_SET_PRIORITY(int prio_, [[maybe_unused]] bool sudo_) +// ################################################################################################# + +std::pair THREAD_NATIVE_PRIOS() +{ + int const _prio_min{ sched_get_priority_min(_PRIO_MODE) }; + int const _prio_max{ sched_get_priority_max(_PRIO_MODE) }; + return std::make_pair(_prio_min, _prio_max); +} + +// ################################################################################################# + +void THREAD_SET_PRIORITY(lua_State* const L_, int const prio_, NativePrioFlag const native_, [[maybe_unused]] SudoFlag const sudo_) { #ifdef PLATFORM_LINUX if (!sudo_) // only root-privileged process can change priorities @@ -366,13 +397,13 @@ void THREAD_SET_PRIORITY(int prio_, [[maybe_unused]] bool sudo_) struct sched_param sp; // prio range [-3,+3] was checked by the caller - sp.sched_priority = gs_prio_remap[prio_ + 3]; - PT_CALL(pthread_setschedparam(pthread_self(), _PRIO_MODE, &sp)); + sp.sched_priority = native_ ? prio_ : gs_prio_remap[prio_ + 3]; + PthreadInvoke(L_, std::source_location::current().function_name(), pthread_setschedparam, pthread_self(), _PRIO_MODE, &sp); } // ################################################################################################# -void THREAD_SET_PRIORITY(std::thread& thread_, int prio_, [[maybe_unused]] bool sudo_) +void THREAD_SET_PRIORITY(lua_State* const L_, std::thread& thread_, int const prio_, NativePrioFlag const native_, [[maybe_unused]] SudoFlag const sudo_) { #ifdef PLATFORM_LINUX if (!sudo_) // only root-privileged process can change priorities @@ -381,28 +412,26 @@ void THREAD_SET_PRIORITY(std::thread& thread_, int prio_, [[maybe_unused]] bool struct sched_param sp; // prio range [-3,+3] was checked by the caller - sp.sched_priority = gs_prio_remap[prio_ + 3]; - PT_CALL(pthread_setschedparam(thread_.native_handle(), _PRIO_MODE, &sp)); + sp.sched_priority = native_ ? prio_ : gs_prio_remap[prio_ + 3]; + PthreadInvoke(L_, std::source_location::current().function_name(), pthread_setschedparam, thread_.native_handle(), _PRIO_MODE, &sp); } // ################################################################################################# #ifdef __PROSPERO__ -void THREAD_SET_AFFINITY(unsigned int aff_) +void THREAD_SET_AFFINITY(lua_State* const L_, unsigned int aff_) { - scePthreadSetaffinity(scePthreadSelf(), aff_); + PthreadInvoke(L_, std::source_location::current().function_name(), scePthreadSetaffinity, scePthreadSelf(), aff_); } #else // __PROSPERO__ -void THREAD_SET_AFFINITY(unsigned int aff_) +void THREAD_SET_AFFINITY(lua_State* const L_, unsigned int aff_) { #if HAVE_WIN32 // "hybrid": Win32 API is available, and pthread too // since pthread_setaffinity_np can be missing (for example mingw), use win32 api instead - if (!SetThreadAffinityMask(GetCurrentThread(), aff_)) { - FAIL("THREAD_SET_AFFINITY", GetLastError()); - } + Win32Invoke(L_, std::source_location::current().function_name(), SetThreadAffinityMask, GetCurrentThread(), aff_); #else // pure pthread int bit = 0; #ifdef __NetBSD__ @@ -422,12 +451,13 @@ void THREAD_SET_AFFINITY(unsigned int aff_) aff_ >>= 1; } #ifdef __ANDROID__ - PT_CALL(sched_setaffinity(pthread_self(), sizeof(cpu_set_t), &cpuset)); + + PthreadInvoke(L_, std::source_location::current().function_name(), sched_setaffinity, pthread_self(), sizeof(cpu_set_t), &cpuset); #elif defined(__NetBSD__) - PT_CALL(pthread_setaffinity_np(pthread_self(), cpuset_size(cpuset), cpuset)); + PthreadInvoke(L_, std::source_location::current().function_name(), pthread_setaffinity_np, pthread_self(), cpuset_size(cpuset), cpuset); cpuset_destroy(cpuset); #else - PT_CALL(pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset)); + PthreadInvoke(L_, std::source_location::current().function_name(), pthread_setaffinity_np, pthread_self(), sizeof(cpu_set_t), &cpuset); #endif #endif // PLATFORM_MINGW } @@ -447,7 +477,7 @@ void THREAD_SETNAME(std::string_view const& name_) void THREAD_SETNAME(std::string_view const& name_) { - // exact API to set the thread name is platform-dependant + // exact API to set the thread name is platform-dependent // if you need to fix the build, or if you know how to fill a hole, tell me (bnt.germain@gmail.com) so that I can submit the fix in github. #if defined PLATFORM_MINGW pthread_setname_np(pthread_self(), name_.data()); diff --git a/src/threading.hpp b/src/threading.hpp index 912c28f..07c1ab3 100644 --- a/src/threading.hpp +++ b/src/threading.hpp @@ -1,6 +1,7 @@ #pragma once #include "platform.h" +#include "unique.hpp" #define THREADAPI_WINDOWS 1 #define THREADAPI_PTHREAD 2 @@ -73,8 +74,15 @@ static constexpr int kThreadPrioMax{ +3 }; // ################################################################################################# // ################################################################################################# +DECLARE_UNIQUE_TYPE(SudoFlag, bool); +DECLARE_UNIQUE_TYPE(NativePrioFlag, bool); + +std::pair THREAD_NATIVE_PRIOS(); + void THREAD_SETNAME(std::string_view const& name_); -void THREAD_SET_PRIORITY(int prio_, bool sudo_); -void THREAD_SET_AFFINITY(unsigned int aff_); -void THREAD_SET_PRIORITY(std::thread& thread_, int prio_, bool sudo_); +void THREAD_SET_PRIORITY(lua_State* L_, int prio_, NativePrioFlag native_, SudoFlag sudo_); + +void THREAD_SET_AFFINITY(lua_State* L_, unsigned int aff_); + +void THREAD_SET_PRIORITY(lua_State* L_, std::thread& thread_, int prio_, NativePrioFlag native_, SudoFlag sudo_); diff --git a/src/universe.hpp b/src/universe.hpp index fac5f50..ab49f86 100644 --- a/src/universe.hpp +++ b/src/universe.hpp @@ -4,6 +4,7 @@ #include "cancel.hpp" #include "keeper.hpp" #include "lanesconf.h" +#include "threading.hpp" #include "tracker.hpp" #include "uniquekey.hpp" @@ -70,9 +71,9 @@ class Universe final #ifdef PLATFORM_LINUX // Linux needs to check, whether it's been run as root - bool const sudo{ geteuid() == 0 }; + SudoFlag const sudo{ geteuid() == 0 }; #else - bool const sudo{ false }; + SudoFlag const sudo{ false }; #endif // PLATFORM_LINUX // for verbose errors -- cgit v1.2.3-55-g6feb