diff options
| author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-04-09 10:12:30 +0200 |
|---|---|---|
| committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-04-09 10:12:30 +0200 |
| commit | 23f25f3a9d327153e4c16ca86d937ec334803a10 (patch) | |
| tree | 110826adcf29554cd59768acdccf3de006e8a7f4 /src | |
| parent | 9b5c27af793a08fd17d1fde93e9512e76536f484 (diff) | |
| download | lanes-23f25f3a9d327153e4c16ca86d937ec334803a10.tar.gz lanes-23f25f3a9d327153e4c16ca86d937ec334803a10.tar.bz2 lanes-23f25f3a9d327153e4c16ca86d937ec334803a10.zip | |
C++ migration: still more threading code cleanup. 'sudo' global moved in the Universe
Diffstat (limited to 'src')
| -rw-r--r-- | src/deep.h | 2 | ||||
| -rw-r--r-- | src/keeper.h | 2 | ||||
| -rw-r--r-- | src/lanes.cpp | 32 | ||||
| -rw-r--r-- | src/state.h | 2 | ||||
| -rw-r--r-- | src/threading.cpp | 22 | ||||
| -rw-r--r-- | src/threading.h | 24 | ||||
| -rw-r--r-- | src/tools.h | 2 | ||||
| -rw-r--r-- | src/universe.cpp | 29 | ||||
| -rw-r--r-- | src/universe.h | 20 |
9 files changed, 67 insertions, 68 deletions
| @@ -19,7 +19,7 @@ extern "C" { | |||
| 19 | #include <atomic> | 19 | #include <atomic> |
| 20 | 20 | ||
| 21 | // forwards | 21 | // forwards |
| 22 | struct Universe; | 22 | class Universe; |
| 23 | 23 | ||
| 24 | enum class LookupMode | 24 | enum class LookupMode |
| 25 | { | 25 | { |
diff --git a/src/keeper.h b/src/keeper.h index 931c1d5..ba5a57b 100644 --- a/src/keeper.h +++ b/src/keeper.h | |||
| @@ -15,7 +15,7 @@ extern "C" { | |||
| 15 | 15 | ||
| 16 | // forwards | 16 | // forwards |
| 17 | enum class LookupMode; | 17 | enum class LookupMode; |
| 18 | struct Universe; | 18 | class Universe; |
| 19 | 19 | ||
| 20 | struct Keeper | 20 | struct Keeper |
| 21 | { | 21 | { |
diff --git a/src/lanes.cpp b/src/lanes.cpp index f5d5130..28f95f6 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp | |||
| @@ -136,7 +136,7 @@ void Lane::startThread(int priority_) | |||
| 136 | m_thread = std::jthread([this]() { lane_main(this); }); | 136 | m_thread = std::jthread([this]() { lane_main(this); }); |
| 137 | if (priority_ != THREAD_PRIO_DEFAULT) | 137 | if (priority_ != THREAD_PRIO_DEFAULT) |
| 138 | { | 138 | { |
| 139 | JTHREAD_SET_PRIORITY(m_thread, priority_); | 139 | JTHREAD_SET_PRIORITY(m_thread, priority_, U->m_sudo); |
| 140 | } | 140 | } |
| 141 | } | 141 | } |
| 142 | 142 | ||
| @@ -784,7 +784,7 @@ LUAG_FUNC(get_debug_threadname) | |||
| 784 | 784 | ||
| 785 | LUAG_FUNC(set_thread_priority) | 785 | LUAG_FUNC(set_thread_priority) |
| 786 | { | 786 | { |
| 787 | int const prio{ (int) luaL_checkinteger(L, 1) }; | 787 | lua_Integer const prio{ luaL_checkinteger(L, 1) }; |
| 788 | // public Lanes API accepts a generic range -3/+3 | 788 | // public Lanes API accepts a generic range -3/+3 |
| 789 | // that will be remapped into the platform-specific scheduler priority scheme | 789 | // that will be remapped into the platform-specific scheduler priority scheme |
| 790 | // On some platforms, -3 is equivalent to -2 and +3 to +2 | 790 | // On some platforms, -3 is equivalent to -2 and +3 to +2 |
| @@ -792,7 +792,7 @@ LUAG_FUNC(set_thread_priority) | |||
| 792 | { | 792 | { |
| 793 | return luaL_error(L, "priority out of range: %d..+%d (%d)", THREAD_PRIO_MIN, THREAD_PRIO_MAX, prio); | 793 | return luaL_error(L, "priority out of range: %d..+%d (%d)", THREAD_PRIO_MIN, THREAD_PRIO_MAX, prio); |
| 794 | } | 794 | } |
| 795 | THREAD_SET_PRIORITY(prio); | 795 | THREAD_SET_PRIORITY(static_cast<int>(prio), universe_get(L)->m_sudo); |
| 796 | return 0; | 796 | return 0; |
| 797 | } | 797 | } |
| 798 | 798 | ||
| @@ -1746,32 +1746,6 @@ static void init_once_LOCKED( void) | |||
| 1746 | #if (defined PLATFORM_OSX) && (defined _UTILBINDTHREADTOCPU) | 1746 | #if (defined PLATFORM_OSX) && (defined _UTILBINDTHREADTOCPU) |
| 1747 | chudInitialize(); | 1747 | chudInitialize(); |
| 1748 | #endif | 1748 | #endif |
| 1749 | |||
| 1750 | //--- | ||
| 1751 | // Linux needs SCHED_RR to change thread priorities, and that is only | ||
| 1752 | // allowed for sudo'ers. SCHED_OTHER (default) has no priorities. | ||
| 1753 | // SCHED_OTHER threads are always lower priority than SCHED_RR. | ||
| 1754 | // | ||
| 1755 | // ^-- those apply to 2.6 kernel. IF **wishful thinking** these | ||
| 1756 | // constraints will change in the future, non-sudo priorities can | ||
| 1757 | // be enabled also for Linux. | ||
| 1758 | // | ||
| 1759 | #ifdef PLATFORM_LINUX | ||
| 1760 | sudo = (geteuid() == 0); // we are root? | ||
| 1761 | |||
| 1762 | // If lower priorities (-2..-1) are wanted, we need to lift the main | ||
| 1763 | // thread to SCHED_RR and 50 (medium) level. Otherwise, we're always below | ||
| 1764 | // the launched threads (even -2). | ||
| 1765 | // | ||
| 1766 | #ifdef LINUX_SCHED_RR | ||
| 1767 | if (sudo) | ||
| 1768 | { | ||
| 1769 | struct sched_param sp; | ||
| 1770 | sp.sched_priority = _PRIO_0; | ||
| 1771 | PT_CALL(pthread_setschedparam(pthread_self(), SCHED_RR, &sp)); | ||
| 1772 | } | ||
| 1773 | #endif // LINUX_SCHED_RR | ||
| 1774 | #endif // PLATFORM_LINUX | ||
| 1775 | } | 1749 | } |
| 1776 | 1750 | ||
| 1777 | // ################################################################################################# | 1751 | // ################################################################################################# |
diff --git a/src/state.h b/src/state.h index 0e35e89..0e069da 100644 --- a/src/state.h +++ b/src/state.h | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | #include "macros_and_utils.h" | 3 | #include "macros_and_utils.h" |
| 4 | 4 | ||
| 5 | // forwards | 5 | // forwards |
| 6 | struct Universe; | 6 | class Universe; |
| 7 | 7 | ||
| 8 | void serialize_require(DEBUGSPEW_PARAM_COMMA(Universe* U) lua_State* L); | 8 | void serialize_require(DEBUGSPEW_PARAM_COMMA(Universe* U) lua_State* L); |
| 9 | 9 | ||
diff --git a/src/threading.cpp b/src/threading.cpp index aab2fa7..4d210d6 100644 --- a/src/threading.cpp +++ b/src/threading.cpp | |||
| @@ -65,12 +65,6 @@ THE SOFTWARE. | |||
| 65 | # include <unistd.h> | 65 | # include <unistd.h> |
| 66 | #endif | 66 | #endif |
| 67 | 67 | ||
| 68 | /* Linux needs to check, whether it's been run as root | ||
| 69 | */ | ||
| 70 | #ifdef PLATFORM_LINUX | ||
| 71 | volatile bool sudo; | ||
| 72 | #endif | ||
| 73 | |||
| 74 | #ifdef PLATFORM_OSX | 68 | #ifdef PLATFORM_OSX |
| 75 | # include "threading_osx.h" | 69 | # include "threading_osx.h" |
| 76 | #endif | 70 | #endif |
| @@ -134,10 +128,10 @@ static int const gs_prio_remap[] = | |||
| 134 | 128 | ||
| 135 | // ############################################################################################### | 129 | // ############################################################################################### |
| 136 | 130 | ||
| 137 | void THREAD_SET_PRIORITY(int prio) | 131 | void THREAD_SET_PRIORITY(int prio_, [[maybe_unused]] bool sudo_) |
| 138 | { | 132 | { |
| 139 | // prio range [-3,+3] was checked by the caller | 133 | // prio range [-3,+3] was checked by the caller |
| 140 | if (!SetThreadPriority(GetCurrentThread(), gs_prio_remap[prio + 3])) | 134 | if (!SetThreadPriority(GetCurrentThread(), gs_prio_remap[prio_ + 3])) |
| 141 | { | 135 | { |
| 142 | FAIL("THREAD_SET_PRIORITY", GetLastError()); | 136 | FAIL("THREAD_SET_PRIORITY", GetLastError()); |
| 143 | } | 137 | } |
| @@ -145,7 +139,7 @@ void THREAD_SET_PRIORITY(int prio) | |||
| 145 | 139 | ||
| 146 | // ############################################################################################### | 140 | // ############################################################################################### |
| 147 | 141 | ||
| 148 | void JTHREAD_SET_PRIORITY(std::jthread& thread_, int prio_) | 142 | void JTHREAD_SET_PRIORITY(std::jthread& thread_, int prio_, [[maybe_unused]] bool sudo_) |
| 149 | { | 143 | { |
| 150 | // prio range [-3,+3] was checked by the caller | 144 | // prio range [-3,+3] was checked by the caller |
| 151 | if (!SetThreadPriority(thread_.native_handle(), gs_prio_remap[prio_ + 3])) | 145 | if (!SetThreadPriority(thread_.native_handle(), gs_prio_remap[prio_ + 3])) |
| @@ -368,25 +362,25 @@ static int select_prio(int prio /* -3..+3 */) | |||
| 368 | return gs_prio_remap[prio + 3]; | 362 | return gs_prio_remap[prio + 3]; |
| 369 | } | 363 | } |
| 370 | 364 | ||
| 371 | void THREAD_SET_PRIORITY(int prio) | 365 | void THREAD_SET_PRIORITY(int prio_, [[maybe_unused]] bool sudo_) |
| 372 | { | 366 | { |
| 373 | #ifdef PLATFORM_LINUX | 367 | #ifdef PLATFORM_LINUX |
| 374 | if (!sudo) // only root-privileged process can change priorities | 368 | if (!sudo_) // only root-privileged process can change priorities |
| 375 | return; | 369 | return; |
| 376 | #endif // PLATFORM_LINUX | 370 | #endif // PLATFORM_LINUX |
| 377 | 371 | ||
| 378 | struct sched_param sp; | 372 | struct sched_param sp; |
| 379 | // prio range [-3,+3] was checked by the caller | 373 | // prio range [-3,+3] was checked by the caller |
| 380 | sp.sched_priority = gs_prio_remap[prio + 3]; | 374 | sp.sched_priority = gs_prio_remap[prio_ + 3]; |
| 381 | PT_CALL(pthread_setschedparam(pthread_self(), _PRIO_MODE, &sp)); | 375 | PT_CALL(pthread_setschedparam(pthread_self(), _PRIO_MODE, &sp)); |
| 382 | } | 376 | } |
| 383 | 377 | ||
| 384 | // ################################################################################################# | 378 | // ################################################################################################# |
| 385 | 379 | ||
| 386 | void JTHREAD_SET_PRIORITY(std::jthread& thread_, int prio_) | 380 | void JTHREAD_SET_PRIORITY(std::jthread& thread_, int prio_, [[maybe_unused]] bool sudo_) |
| 387 | { | 381 | { |
| 388 | #ifdef PLATFORM_LINUX | 382 | #ifdef PLATFORM_LINUX |
| 389 | if (!sudo) // only root-privileged process can change priorities | 383 | if (!sudo_) // only root-privileged process can change priorities |
| 390 | return; | 384 | return; |
| 391 | #endif // PLATFORM_LINUX | 385 | #endif // PLATFORM_LINUX |
| 392 | 386 | ||
diff --git a/src/threading.h b/src/threading.h index c443c82..f38b2de 100644 --- a/src/threading.h +++ b/src/threading.h | |||
| @@ -58,33 +58,19 @@ static constexpr int THREAD_PRIO_MAX{ +3 }; | |||
| 58 | #endif // PLATFORM_WIN32 | 58 | #endif // PLATFORM_WIN32 |
| 59 | #include <pthread.h> | 59 | #include <pthread.h> |
| 60 | 60 | ||
| 61 | // Yield is non-portable: | 61 | #if defined(PLATFORM_LINUX) && !defined(LINUX_SCHED_RR) |
| 62 | // | ||
| 63 | // OS X 10.4.8/9 has pthread_yield_np() | ||
| 64 | // Linux 2.4 has pthread_yield() if _GNU_SOURCE is #defined | ||
| 65 | // FreeBSD 6.2 has pthread_yield() | ||
| 66 | // ... | ||
| 67 | // | ||
| 68 | |||
| 69 | #if defined(PLATFORM_LINUX) | ||
| 70 | extern volatile bool sudo; | ||
| 71 | # ifdef LINUX_SCHED_RR | ||
| 72 | # define THREAD_PRIO_MIN (sudo ? -3 : 0) | ||
| 73 | # else | ||
| 74 | static constexpr int THREAD_PRIO_MIN{ 0 }; | 62 | static constexpr int THREAD_PRIO_MIN{ 0 }; |
| 75 | #endif | ||
| 76 | # define THREAD_PRIO_MAX (sudo ? +3 : 0) | ||
| 77 | #else | 63 | #else |
| 78 | static constexpr int THREAD_PRIO_MIN{ -3 }; | 64 | static constexpr int THREAD_PRIO_MIN{ -3 }; |
| 79 | static constexpr int THREAD_PRIO_MAX{ +3 }; | ||
| 80 | #endif | 65 | #endif |
| 66 | static constexpr int THREAD_PRIO_MAX{ +3 }; | ||
| 81 | 67 | ||
| 82 | #endif // THREADAPI == THREADAPI_WINDOWS | 68 | #endif // THREADAPI == THREADAPI_PTHREAD |
| 83 | // ################################################################################################## | 69 | // ################################################################################################## |
| 84 | // ################################################################################################## | 70 | // ################################################################################################## |
| 85 | 71 | ||
| 86 | void THREAD_SETNAME(char const* _name); | 72 | void THREAD_SETNAME(char const* _name); |
| 87 | void THREAD_SET_PRIORITY(int prio); | 73 | void THREAD_SET_PRIORITY(int prio_, bool sudo_); |
| 88 | void THREAD_SET_AFFINITY(unsigned int aff); | 74 | void THREAD_SET_AFFINITY(unsigned int aff); |
| 89 | 75 | ||
| 90 | void JTHREAD_SET_PRIORITY(std::jthread& thread_, int prio_); | 76 | void JTHREAD_SET_PRIORITY(std::jthread& thread_, int prio_, bool sudo_); |
diff --git a/src/tools.h b/src/tools.h index c1a8534..7d9aaab 100644 --- a/src/tools.h +++ b/src/tools.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | #include "macros_and_utils.h" | 6 | #include "macros_and_utils.h" |
| 7 | 7 | ||
| 8 | // forwards | 8 | // forwards |
| 9 | struct Universe; | 9 | class Universe; |
| 10 | 10 | ||
| 11 | // ################################################################################################ | 11 | // ################################################################################################ |
| 12 | 12 | ||
diff --git a/src/universe.cpp b/src/universe.cpp index 66da147..290e547 100644 --- a/src/universe.cpp +++ b/src/universe.cpp | |||
| @@ -43,6 +43,35 @@ static constexpr UniqueKey UNIVERSE_LIGHT_REGKEY{ 0x3663C07C742CEB81ull }; | |||
| 43 | 43 | ||
| 44 | // ################################################################################################ | 44 | // ################################################################################################ |
| 45 | 45 | ||
| 46 | Universe::Universe() | ||
| 47 | { | ||
| 48 | //--- | ||
| 49 | // Linux needs SCHED_RR to change thread priorities, and that is only | ||
| 50 | // allowed for sudo'ers. SCHED_OTHER (default) has no priorities. | ||
| 51 | // SCHED_OTHER threads are always lower priority than SCHED_RR. | ||
| 52 | // | ||
| 53 | // ^-- those apply to 2.6 kernel. IF **wishful thinking** these | ||
| 54 | // constraints will change in the future, non-sudo priorities can | ||
| 55 | // be enabled also for Linux. | ||
| 56 | // | ||
| 57 | #ifdef PLATFORM_LINUX | ||
| 58 | // If lower priorities (-2..-1) are wanted, we need to lift the main | ||
| 59 | // thread to SCHED_RR and 50 (medium) level. Otherwise, we're always below | ||
| 60 | // the launched threads (even -2). | ||
| 61 | // | ||
| 62 | #ifdef LINUX_SCHED_RR | ||
| 63 | if (m_sudo) | ||
| 64 | { | ||
| 65 | struct sched_param sp; | ||
| 66 | sp.sched_priority = _PRIO_0; | ||
| 67 | PT_CALL(pthread_setschedparam(pthread_self(), SCHED_RR, &sp)); | ||
| 68 | } | ||
| 69 | #endif // LINUX_SCHED_RR | ||
| 70 | #endif // PLATFORM_LINUX | ||
| 71 | } | ||
| 72 | |||
| 73 | // ################################################################################################ | ||
| 74 | |||
| 46 | // only called from the master state | 75 | // only called from the master state |
| 47 | Universe* universe_create(lua_State* L) | 76 | Universe* universe_create(lua_State* L) |
| 48 | { | 77 | { |
diff --git a/src/universe.h b/src/universe.h index 38885cb..f4211af 100644 --- a/src/universe.h +++ b/src/universe.h | |||
| @@ -119,9 +119,17 @@ class ProtectedAllocator : public AllocatorDefinition | |||
| 119 | 119 | ||
| 120 | // everything regarding the Lanes universe is stored in that global structure | 120 | // everything regarding the Lanes universe is stored in that global structure |
| 121 | // held as a full userdata in the master Lua state that required it for the first time | 121 | // held as a full userdata in the master Lua state that required it for the first time |
| 122 | // don't forget to initialize all members in LG_configure() | 122 | class Universe |
| 123 | struct Universe | ||
| 124 | { | 123 | { |
| 124 | public: | ||
| 125 | |||
| 126 | #ifdef PLATFORM_LINUX | ||
| 127 | // Linux needs to check, whether it's been run as root | ||
| 128 | bool const m_sudo{ geteuid() == 0 }; | ||
| 129 | #else | ||
| 130 | bool const m_sudo{ false }; | ||
| 131 | #endif // PLATFORM_LINUX | ||
| 132 | |||
| 125 | // for verbose errors | 133 | // for verbose errors |
| 126 | bool verboseErrors{ false }; | 134 | bool verboseErrors{ false }; |
| 127 | 135 | ||
| @@ -155,6 +163,7 @@ struct Universe | |||
| 155 | // require() serialization | 163 | // require() serialization |
| 156 | std::recursive_mutex require_cs; | 164 | std::recursive_mutex require_cs; |
| 157 | 165 | ||
| 166 | // metatable unique identifiers | ||
| 158 | std::atomic<lua_Integer> next_mt_id{ 1 }; | 167 | std::atomic<lua_Integer> next_mt_id{ 1 }; |
| 159 | 168 | ||
| 160 | #if USE_DEBUG_SPEW() | 169 | #if USE_DEBUG_SPEW() |
| @@ -165,6 +174,13 @@ struct Universe | |||
| 165 | // After a lane has removed itself from the chain, it still performs some processing. | 174 | // After a lane has removed itself from the chain, it still performs some processing. |
| 166 | // The terminal desinit sequence should wait for all such processing to terminate before force-killing threads | 175 | // The terminal desinit sequence should wait for all such processing to terminate before force-killing threads |
| 167 | std::atomic<int> selfdestructing_count{ 0 }; | 176 | std::atomic<int> selfdestructing_count{ 0 }; |
| 177 | |||
| 178 | Universe(); | ||
| 179 | ~Universe() = default; | ||
| 180 | Universe(Universe const&) = delete; | ||
| 181 | Universe(Universe&&) = delete; | ||
| 182 | Universe& operator=(Universe const&) = delete; | ||
| 183 | Universe& operator=(Universe&&) = delete; | ||
| 168 | }; | 184 | }; |
| 169 | 185 | ||
| 170 | // ################################################################################################ | 186 | // ################################################################################################ |
