diff options
author | Benoit Germain <benoit.germain@ubisoft.com> | 2023-07-28 14:48:16 +0200 |
---|---|---|
committer | Benoit Germain <benoit.germain@ubisoft.com> | 2023-07-28 14:48:16 +0200 |
commit | d73f4cee37b0a43edadf9709289798ee4bfccc0e (patch) | |
tree | 8c5ce974f9b148e343756d7c667125bee7b22351 | |
parent | 886eb0365f38d455ca2c9ff8dd3ddf12fedb6960 (diff) | |
download | lanes-d73f4cee37b0a43edadf9709289798ee4bfccc0e.tar.gz lanes-d73f4cee37b0a43edadf9709289798ee4bfccc0e.tar.bz2 lanes-d73f4cee37b0a43edadf9709289798ee4bfccc0e.zip |
tweaks to linux thread priority management
-rw-r--r-- | CHANGES | 6 | ||||
-rw-r--r-- | src/lanes.c | 77 | ||||
-rw-r--r-- | src/threading.c | 137 | ||||
-rw-r--r-- | src/threading.h | 4 |
4 files changed, 122 insertions, 102 deletions
@@ -1,5 +1,11 @@ | |||
1 | CHANGES: | 1 | CHANGES: |
2 | 2 | ||
3 | CHANGE 155: BGe 28-Jul-23 | ||
4 | * tweaks to linux thread priority management: do nothing if not super-user. if super-user, do nothing if nothing is provided (instead of trying to force a prio when LINUX_SCHED_RR is defined). | ||
5 | |||
6 | CHANGE 154: eligovision 1-Mar-22 | ||
7 | * Fix 3-parametrized __lanesclone | ||
8 | |||
3 | CHANGE 153: BGe 17-Feb-22 | 9 | CHANGE 153: BGe 17-Feb-22 |
4 | * NEVER use allocator obtained from lua_getallocf to allocate stuff manually when compiling for LuaJIT | 10 | * NEVER use allocator obtained from lua_getallocf to allocate stuff manually when compiling for LuaJIT |
5 | 11 | ||
diff --git a/src/lanes.c b/src/lanes.c index cd1d4f1..9f6a4d6 100644 --- a/src/lanes.c +++ b/src/lanes.c | |||
@@ -1052,21 +1052,22 @@ LUAG_FUNC( lane_new) | |||
1052 | Lane** ud; | 1052 | Lane** ud; |
1053 | 1053 | ||
1054 | char const* libs_str = lua_tostring( L, 2); | 1054 | char const* libs_str = lua_tostring( L, 2); |
1055 | int const priority = (int) luaL_optinteger( L, 3, 0); | 1055 | bool_t const have_priority = !lua_isnoneornil( L, 3); |
1056 | uint_t globals_idx = lua_isnoneornil( L, 4) ? 0 : 4; | 1056 | int const priority = have_priority ? (int) lua_tointeger( L, 3) : THREAD_PRIO_DEFAULT; |
1057 | uint_t package_idx = lua_isnoneornil( L, 5) ? 0 : 5; | 1057 | uint_t const globals_idx = lua_isnoneornil( L, 4) ? 0 : 4; |
1058 | uint_t required_idx = lua_isnoneornil( L, 6) ? 0 : 6; | 1058 | uint_t const package_idx = lua_isnoneornil( L, 5) ? 0 : 5; |
1059 | uint_t gc_cb_idx = lua_isnoneornil( L, 7) ? 0 : 7; | 1059 | uint_t const required_idx = lua_isnoneornil( L, 6) ? 0 : 6; |
1060 | uint_t const gc_cb_idx = lua_isnoneornil( L, 7) ? 0 : 7; | ||
1060 | 1061 | ||
1061 | #define FIXED_ARGS 7 | 1062 | #define FIXED_ARGS 7 |
1062 | int const nargs = lua_gettop(L) - FIXED_ARGS; | 1063 | int const nargs = lua_gettop(L) - FIXED_ARGS; |
1063 | Universe* U = universe_get( L); | 1064 | Universe* const U = universe_get( L); |
1064 | ASSERT_L( nargs >= 0); | 1065 | ASSERT_L( nargs >= 0); |
1065 | 1066 | ||
1066 | // public Lanes API accepts a generic range -3/+3 | 1067 | // public Lanes API accepts a generic range -3/+3 |
1067 | // that will be remapped into the platform-specific scheduler priority scheme | 1068 | // that will be remapped into the platform-specific scheduler priority scheme |
1068 | // On some platforms, -3 is equivalent to -2 and +3 to +2 | 1069 | // On some platforms, -3 is equivalent to -2 and +3 to +2 |
1069 | if( priority < THREAD_PRIO_MIN || priority > THREAD_PRIO_MAX) | 1070 | if( have_priority && (priority < THREAD_PRIO_MIN || priority > THREAD_PRIO_MAX)) |
1070 | { | 1071 | { |
1071 | return luaL_error( L, "Priority out of range: %d..+%d (%d)", THREAD_PRIO_MIN, THREAD_PRIO_MAX, priority); | 1072 | return luaL_error( L, "Priority out of range: %d..+%d (%d)", THREAD_PRIO_MIN, THREAD_PRIO_MAX, priority); |
1072 | } | 1073 | } |
@@ -1076,12 +1077,12 @@ LUAG_FUNC( lane_new) | |||
1076 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 1077 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); |
1077 | 1078 | ||
1078 | // populate with selected libraries at the same time | 1079 | // populate with selected libraries at the same time |
1079 | L2 = luaG_newstate( U, L, libs_str); // L // L2 | 1080 | L2 = luaG_newstate( U, L, libs_str); // L // L2 |
1080 | 1081 | ||
1081 | STACK_GROW( L2, nargs + 3); // | 1082 | STACK_GROW( L2, nargs + 3); // |
1082 | STACK_CHECK( L2, 0); | 1083 | STACK_CHECK( L2, 0); |
1083 | 1084 | ||
1084 | STACK_GROW( L, 3); // func libs priority globals package required gc_cb [... args ...] | 1085 | STACK_GROW( L, 3); // func libs priority globals package required gc_cb [... args ...] |
1085 | STACK_CHECK( L, 0); | 1086 | STACK_CHECK( L, 0); |
1086 | 1087 | ||
1087 | // give a default "Lua" name to the thread to see VM name in Decoda debugger | 1088 | // give a default "Lua" name to the thread to see VM name in Decoda debugger |
@@ -1110,8 +1111,8 @@ LUAG_FUNC( lane_new) | |||
1110 | return luaL_error( L, "expected required module list as a table, got %s", luaL_typename( L, required_idx)); | 1111 | return luaL_error( L, "expected required module list as a table, got %s", luaL_typename( L, required_idx)); |
1111 | } | 1112 | } |
1112 | 1113 | ||
1113 | lua_pushnil( L); // func libs priority globals package required gc_cb [... args ...] nil | 1114 | lua_pushnil( L); // func libs priority globals package required gc_cb [... args ...] nil |
1114 | while( lua_next( L, required_idx) != 0) // func libs priority globals package required gc_cb [... args ...] n "modname" | 1115 | while( lua_next( L, required_idx) != 0) // func libs priority globals package required gc_cb [... args ...] n "modname" |
1115 | { | 1116 | { |
1116 | if( lua_type( L, -1) != LUA_TSTRING || lua_type( L, -2) != LUA_TNUMBER || lua_tonumber( L, -2) != nbRequired) | 1117 | if( lua_type( L, -1) != LUA_TSTRING || lua_type( L, -2) != LUA_TNUMBER || lua_tonumber( L, -2) != nbRequired) |
1117 | { | 1118 | { |
@@ -1125,29 +1126,29 @@ LUAG_FUNC( lane_new) | |||
1125 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: require '%s'\n" INDENT_END, name)); | 1126 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: require '%s'\n" INDENT_END, name)); |
1126 | 1127 | ||
1127 | // require the module in the target lane | 1128 | // require the module in the target lane |
1128 | lua_getglobal( L2, "require"); // require()? | 1129 | lua_getglobal( L2, "require"); // require()? |
1129 | if( lua_isnil( L2, -1)) | 1130 | if( lua_isnil( L2, -1)) |
1130 | { | 1131 | { |
1131 | lua_pop( L2, 1); // | 1132 | lua_pop( L2, 1); // |
1132 | luaL_error( L, "cannot pre-require modules without loading 'package' library first"); | 1133 | luaL_error( L, "cannot pre-require modules without loading 'package' library first"); |
1133 | } | 1134 | } |
1134 | else | 1135 | else |
1135 | { | 1136 | { |
1136 | lua_pushlstring( L2, name, len); // require() name | 1137 | lua_pushlstring( L2, name, len); // require() name |
1137 | if( lua_pcall( L2, 1, 1, 0) != LUA_OK) // ret/errcode | 1138 | if( lua_pcall( L2, 1, 1, 0) != LUA_OK) // ret/errcode |
1138 | { | 1139 | { |
1139 | // propagate error to main state if any | 1140 | // propagate error to main state if any |
1140 | luaG_inter_move( U, L2, L, 1, eLM_LaneBody); // func libs priority globals package required gc_cb [... args ...] n "modname" error | 1141 | luaG_inter_move( U, L2, L, 1, eLM_LaneBody); // func libs priority globals package required gc_cb [... args ...] n "modname" error |
1141 | return lua_error( L); | 1142 | return lua_error( L); |
1142 | } | 1143 | } |
1143 | // after requiring the module, register the functions it exported in our name<->function database | 1144 | // after requiring the module, register the functions it exported in our name<->function database |
1144 | populate_func_lookup_table( L2, -1, name); | 1145 | populate_func_lookup_table( L2, -1, name); |
1145 | lua_pop( L2, 1); // | 1146 | lua_pop( L2, 1); // |
1146 | } | 1147 | } |
1147 | } | 1148 | } |
1148 | lua_pop( L, 1); // func libs priority globals package required gc_cb [... args ...] n | 1149 | lua_pop( L, 1); // func libs priority globals package required gc_cb [... args ...] n |
1149 | ++ nbRequired; | 1150 | ++ nbRequired; |
1150 | } // func libs priority globals package required gc_cb [... args ...] | 1151 | } // func libs priority globals package required gc_cb [... args ...] |
1151 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 1152 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); |
1152 | } | 1153 | } |
1153 | STACK_MID( L, 0); | 1154 | STACK_MID( L, 0); |
@@ -1165,17 +1166,17 @@ LUAG_FUNC( lane_new) | |||
1165 | } | 1166 | } |
1166 | 1167 | ||
1167 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 1168 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); |
1168 | lua_pushnil( L); // func libs priority globals package required gc_cb [... args ...] nil | 1169 | lua_pushnil( L); // func libs priority globals package required gc_cb [... args ...] nil |
1169 | // Lua 5.2 wants us to push the globals table on the stack | 1170 | // Lua 5.2 wants us to push the globals table on the stack |
1170 | lua_pushglobaltable( L2); // _G | 1171 | lua_pushglobaltable( L2); // _G |
1171 | while( lua_next( L, globals_idx)) // func libs priority globals package required gc_cb [... args ...] k v | 1172 | while( lua_next( L, globals_idx)) // func libs priority globals package required gc_cb [... args ...] k v |
1172 | { | 1173 | { |
1173 | luaG_inter_copy( U, L, L2, 2, eLM_LaneBody); // _G k v | 1174 | luaG_inter_copy( U, L, L2, 2, eLM_LaneBody); // _G k v |
1174 | // assign it in L2's globals table | 1175 | // assign it in L2's globals table |
1175 | lua_rawset( L2, -3); // _G | 1176 | lua_rawset( L2, -3); // _G |
1176 | lua_pop( L, 1); // func libs priority globals package required gc_cb [... args ...] k | 1177 | lua_pop( L, 1); // func libs priority globals package required gc_cb [... args ...] k |
1177 | } // func libs priority globals package required gc_cb [... args ...] | 1178 | } // func libs priority globals package required gc_cb [... args ...] |
1178 | lua_pop( L2, 1); // | 1179 | lua_pop( L2, 1); // |
1179 | 1180 | ||
1180 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 1181 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); |
1181 | } | 1182 | } |
@@ -1188,8 +1189,8 @@ LUAG_FUNC( lane_new) | |||
1188 | int res; | 1189 | int res; |
1189 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: transfer lane body\n" INDENT_END)); | 1190 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: transfer lane body\n" INDENT_END)); |
1190 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 1191 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); |
1191 | lua_pushvalue( L, 1); // func libs priority globals package required gc_cb [... args ...] func | 1192 | lua_pushvalue( L, 1); // func libs priority globals package required gc_cb [... args ...] func |
1192 | res = luaG_inter_move( U, L, L2, 1, eLM_LaneBody); // func libs priority globals package required gc_cb [... args ...] // func | 1193 | res = luaG_inter_move( U, L, L2, 1, eLM_LaneBody); // func libs priority globals package required gc_cb [... args ...] // func |
1193 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 1194 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); |
1194 | if( res != 0) | 1195 | if( res != 0) |
1195 | { | 1196 | { |
@@ -1199,7 +1200,7 @@ LUAG_FUNC( lane_new) | |||
1199 | else if( lua_type( L, 1) == LUA_TSTRING) | 1200 | else if( lua_type( L, 1) == LUA_TSTRING) |
1200 | { | 1201 | { |
1201 | // compile the string | 1202 | // compile the string |
1202 | if( luaL_loadstring( L2, lua_tostring( L, 1)) != 0) // func | 1203 | if( luaL_loadstring( L2, lua_tostring( L, 1)) != 0) // func |
1203 | { | 1204 | { |
1204 | return luaL_error( L, "error when parsing lane function code"); | 1205 | return luaL_error( L, "error when parsing lane function code"); |
1205 | } | 1206 | } |
@@ -1214,7 +1215,7 @@ LUAG_FUNC( lane_new) | |||
1214 | int res; | 1215 | int res; |
1215 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: transfer lane arguments\n" INDENT_END)); | 1216 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: transfer lane arguments\n" INDENT_END)); |
1216 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 1217 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); |
1217 | res = luaG_inter_move( U, L, L2, nargs, eLM_LaneBody); // func libs priority globals package required gc_cb // func [... args ...] | 1218 | res = luaG_inter_move( U, L, L2, nargs, eLM_LaneBody); // func libs priority globals package required gc_cb // func [... args ...] |
1218 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 1219 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); |
1219 | if( res != 0) | 1220 | if( res != 0) |
1220 | { | 1221 | { |
@@ -1267,23 +1268,23 @@ LUAG_FUNC( lane_new) | |||
1267 | 1268 | ||
1268 | // Set metatable for the userdata | 1269 | // Set metatable for the userdata |
1269 | // | 1270 | // |
1270 | lua_pushvalue( L, lua_upvalueindex( 1)); // func libs priority globals package required gc_cb lane mt | 1271 | lua_pushvalue( L, lua_upvalueindex( 1)); // func libs priority globals package required gc_cb lane mt |
1271 | lua_setmetatable( L, -2); // func libs priority globals package required gc_cb lane | 1272 | lua_setmetatable( L, -2); // func libs priority globals package required gc_cb lane |
1272 | STACK_MID( L, 1); | 1273 | STACK_MID( L, 1); |
1273 | 1274 | ||
1274 | // Create uservalue for the userdata | 1275 | // Create uservalue for the userdata |
1275 | // (this is where lane body return values will be stored when the handle is indexed by a numeric key) | 1276 | // (this is where lane body return values will be stored when the handle is indexed by a numeric key) |
1276 | lua_newtable( L); // func libs cancelstep priority globals package required gc_cb lane uv | 1277 | lua_newtable( L); // func libs cancelstep priority globals package required gc_cb lane uv |
1277 | 1278 | ||
1278 | // Store the gc_cb callback in the uservalue | 1279 | // Store the gc_cb callback in the uservalue |
1279 | if( gc_cb_idx > 0) | 1280 | if( gc_cb_idx > 0) |
1280 | { | 1281 | { |
1281 | push_unique_key( L, GCCB_KEY); // func libs priority globals package required gc_cb lane uv k | 1282 | push_unique_key( L, GCCB_KEY); // func libs priority globals package required gc_cb lane uv k |
1282 | lua_pushvalue( L, gc_cb_idx); // func libs priority globals package required gc_cb lane uv k gc_cb | 1283 | lua_pushvalue( L, gc_cb_idx); // func libs priority globals package required gc_cb lane uv k gc_cb |
1283 | lua_rawset( L, -3); // func libs priority globals package required gc_cb lane uv | 1284 | lua_rawset( L, -3); // func libs priority globals package required gc_cb lane uv |
1284 | } | 1285 | } |
1285 | 1286 | ||
1286 | lua_setiuservalue( L, -2, 1); // func libs priority globals package required gc_cb lane | 1287 | lua_setiuservalue( L, -2, 1); // func libs priority globals package required gc_cb lane |
1287 | 1288 | ||
1288 | // Store 's' in the lane's registry, for 'cancel_test()' (we do cancel tests at pending send/receive). | 1289 | // Store 's' in the lane's registry, for 'cancel_test()' (we do cancel tests at pending send/receive). |
1289 | REGISTRY_SET( L2, CANCEL_TEST_KEY, lua_pushlightuserdata( L2, s)); // func [... args ...] | 1290 | REGISTRY_SET( L2, CANCEL_TEST_KEY, lua_pushlightuserdata( L2, s)); // func [... args ...] |
diff --git a/src/threading.c b/src/threading.c index 183dc87..2b68503 100644 --- a/src/threading.c +++ b/src/threading.c | |||
@@ -323,9 +323,12 @@ void THREAD_CREATE( THREAD_T* ref, THREAD_RETURN_T (__stdcall *func)( void*), vo | |||
323 | FAIL( "CreateThread", GetLastError()); | 323 | FAIL( "CreateThread", GetLastError()); |
324 | } | 324 | } |
325 | 325 | ||
326 | if (!SetThreadPriority( h, gs_prio_remap[prio + 3])) | 326 | if (prio != THREAD_PRIO_DEFAULT) |
327 | { | 327 | { |
328 | FAIL( "SetThreadPriority", GetLastError()); | 328 | if (!SetThreadPriority( h, gs_prio_remap[prio + 3])) |
329 | { | ||
330 | FAIL( "SetThreadPriority", GetLastError()); | ||
331 | } | ||
329 | } | 332 | } |
330 | 333 | ||
331 | *ref = h; | 334 | *ref = h; |
@@ -681,7 +684,7 @@ static int const gs_prio_remap[] = | |||
681 | // least OS specific settings. Hopefully, Linuxes and OS X versions | 684 | // least OS specific settings. Hopefully, Linuxes and OS X versions |
682 | // are uniform enough, among each other... | 685 | // are uniform enough, among each other... |
683 | // | 686 | // |
684 | # if defined PLATFORM_OSX | 687 | # if defined PLATFORM_OSX |
685 | // AK 10-Apr-07 (OS X PowerPC 10.4.9): | 688 | // AK 10-Apr-07 (OS X PowerPC 10.4.9): |
686 | // | 689 | // |
687 | // With SCHED_RR, 26 seems to be the "normal" priority, where setting | 690 | // With SCHED_RR, 26 seems to be the "normal" priority, where setting |
@@ -694,85 +697,92 @@ static int const gs_prio_remap[] = | |||
694 | // priority limits. This could imply, user mode applications won't | 697 | // priority limits. This could imply, user mode applications won't |
695 | // be able to use values outside of that range. | 698 | // be able to use values outside of that range. |
696 | // | 699 | // |
697 | # define _PRIO_MODE SCHED_OTHER | 700 | # define _PRIO_MODE SCHED_OTHER |
698 | 701 | ||
699 | // OS X 10.4.9 (PowerPC) gives ENOTSUP for process scope | 702 | // OS X 10.4.9 (PowerPC) gives ENOTSUP for process scope |
700 | //#define _PRIO_SCOPE PTHREAD_SCOPE_PROCESS | 703 | //#define _PRIO_SCOPE PTHREAD_SCOPE_PROCESS |
701 | 704 | ||
702 | # define _PRIO_HI 32 // seems to work (_carefully_ picked!) | 705 | # define _PRIO_HI 32 // seems to work (_carefully_ picked!) |
703 | # define _PRIO_0 26 // detected | 706 | # define _PRIO_0 26 // detected |
704 | # define _PRIO_LO 1 // seems to work (tested) | 707 | # define _PRIO_LO 1 // seems to work (tested) |
705 | 708 | ||
706 | # elif defined PLATFORM_LINUX | 709 | # elif defined PLATFORM_LINUX |
707 | // (based on Ubuntu Linux 2.6.15 kernel) | 710 | // (based on Ubuntu Linux 2.6.15 kernel) |
708 | // | 711 | // |
709 | // SCHED_OTHER is the default policy, but does not allow for priorities. | 712 | // SCHED_OTHER is the default policy, but does not allow for priorities. |
710 | // SCHED_RR allows priorities, all of which (1..99) are higher than | 713 | // SCHED_RR allows priorities, all of which (1..99) are higher than |
711 | // a thread with SCHED_OTHER policy. | 714 | // a thread with SCHED_OTHER policy. |
712 | // | 715 | // |
713 | // <http://kerneltrap.org/node/6080> | 716 | // <http://kerneltrap.org/node/6080> |
714 | // <http://en.wikipedia.org/wiki/Native_POSIX_Thread_Library> | 717 | // <http://en.wikipedia.org/wiki/Native_POSIX_Thread_Library> |
715 | // <http://www.net.in.tum.de/~gregor/docs/pthread-scheduling.html> | 718 | // <http://www.net.in.tum.de/~gregor/docs/pthread-scheduling.html> |
716 | // | 719 | // |
717 | // Manuals suggest checking #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING, | 720 | // Manuals suggest checking #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING, |
718 | // but even Ubuntu does not seem to define it. | 721 | // but even Ubuntu does not seem to define it. |
719 | // | 722 | // |
720 | # define _PRIO_MODE SCHED_RR | 723 | # define _PRIO_MODE SCHED_RR |
721 | 724 | ||
722 | // NTLP 2.5: only system scope allowed (being the basic reason why | 725 | // NTLP 2.5: only system scope allowed (being the basic reason why |
723 | // root privileges are required..) | 726 | // root privileges are required..) |
724 | //#define _PRIO_SCOPE PTHREAD_SCOPE_PROCESS | 727 | //#define _PRIO_SCOPE PTHREAD_SCOPE_PROCESS |
725 | 728 | ||
726 | # define _PRIO_HI 99 | 729 | # define _PRIO_HI 99 |
727 | # define _PRIO_0 50 | 730 | # define _PRIO_0 50 |
728 | # define _PRIO_LO 1 | 731 | # define _PRIO_LO 1 |
729 | 732 | ||
730 | # elif defined(PLATFORM_BSD) | 733 | # elif defined(PLATFORM_BSD) |
731 | // | 734 | // |
732 | // <http://www.net.in.tum.de/~gregor/docs/pthread-scheduling.html> | 735 | // <http://www.net.in.tum.de/~gregor/docs/pthread-scheduling.html> |
733 | // | 736 | // |
734 | // "When control over the thread scheduling is desired, then FreeBSD | 737 | // "When control over the thread scheduling is desired, then FreeBSD |
735 | // with the libpthread implementation is by far the best choice .." | 738 | // with the libpthread implementation is by far the best choice .." |
736 | // | 739 | // |
737 | # define _PRIO_MODE SCHED_OTHER | 740 | # define _PRIO_MODE SCHED_OTHER |
738 | # define _PRIO_SCOPE PTHREAD_SCOPE_PROCESS | 741 | # define _PRIO_SCOPE PTHREAD_SCOPE_PROCESS |
739 | # define _PRIO_HI 31 | 742 | # define _PRIO_HI 31 |
740 | # define _PRIO_0 15 | 743 | # define _PRIO_0 15 |
741 | # define _PRIO_LO 1 | 744 | # define _PRIO_LO 1 |
742 | 745 | ||
743 | # elif defined(PLATFORM_CYGWIN) | 746 | # elif defined(PLATFORM_CYGWIN) |
744 | // | 747 | // |
745 | // TBD: Find right values for Cygwin | 748 | // TBD: Find right values for Cygwin |
746 | // | 749 | // |
747 | # elif defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC) | 750 | # elif defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC) |
748 | // any other value not supported by win32-pthread as of version 2.9.1 | 751 | // any other value not supported by win32-pthread as of version 2.9.1 |
749 | # define _PRIO_MODE SCHED_OTHER | 752 | # define _PRIO_MODE SCHED_OTHER |
750 | 753 | ||
751 | // PTHREAD_SCOPE_PROCESS not supported by win32-pthread as of version 2.9.1 | 754 | // PTHREAD_SCOPE_PROCESS not supported by win32-pthread as of version 2.9.1 |
752 | //#define _PRIO_SCOPE PTHREAD_SCOPE_SYSTEM // but do we need this at all to start with? | 755 | //#define _PRIO_SCOPE PTHREAD_SCOPE_SYSTEM // but do we need this at all to start with? |
753 | THREAD_PRIORITY_IDLE, THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_ABOVE_NORMAL, THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_TIME_CRITICAL | 756 | THREAD_PRIORITY_IDLE, THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_ABOVE_NORMAL, THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_TIME_CRITICAL |
754 | 757 | ||
755 | # else | 758 | # else |
756 | # error "Unknown OS: not implemented!" | 759 | # error "Unknown OS: not implemented!" |
757 | # endif | 760 | # endif |
758 | 761 | ||
759 | #if defined _PRIO_0 | 762 | #if defined _PRIO_0 |
760 | # define _PRIO_AN (_PRIO_0 + ((_PRIO_HI-_PRIO_0)/2)) | 763 | # define _PRIO_AN (_PRIO_0 + ((_PRIO_HI-_PRIO_0)/2)) |
761 | # define _PRIO_BN (_PRIO_LO + ((_PRIO_0-_PRIO_LO)/2)) | 764 | # define _PRIO_BN (_PRIO_LO + ((_PRIO_0-_PRIO_LO)/2)) |
762 | 765 | ||
763 | _PRIO_LO, _PRIO_LO, _PRIO_BN, _PRIO_0, _PRIO_AN, _PRIO_HI, _PRIO_HI | 766 | _PRIO_LO, _PRIO_LO, _PRIO_BN, _PRIO_0, _PRIO_AN, _PRIO_HI, _PRIO_HI |
764 | #endif // _PRIO_0 | 767 | #endif // _PRIO_0 |
765 | }; | 768 | }; |
766 | 769 | ||
770 | static int select_prio(int prio /* -3..+3 */) | ||
771 | { | ||
772 | if (prio == THREAD_PRIO_DEFAULT) | ||
773 | prio = 0; | ||
774 | // prio range [-3,+3] was checked by the caller | ||
775 | return gs_prio_remap[prio + 3]; | ||
776 | } | ||
777 | |||
767 | void THREAD_CREATE( THREAD_T* ref, THREAD_RETURN_T (*func)( void*), void* data, int prio /* -3..+3 */) | 778 | void THREAD_CREATE( THREAD_T* ref, THREAD_RETURN_T (*func)( void*), void* data, int prio /* -3..+3 */) |
768 | { | 779 | { |
769 | pthread_attr_t a; | 780 | pthread_attr_t a; |
770 | bool_t const normal = | 781 | bool_t const change_priority = |
771 | #if defined(PLATFORM_LINUX) && defined(LINUX_SCHED_RR) | 782 | #if defined(PLATFORM_LINUX) && defined(LINUX_SCHED_RR) |
772 | !sudo; // with sudo, even normal thread must use SCHED_RR | 783 | sudo && // with sudo, even normal thread must use SCHED_RR |
773 | #else | ||
774 | (prio == 0); | ||
775 | #endif | 784 | #endif |
785 | (prio != THREAD_PRIO_DEFAULT); | ||
776 | 786 | ||
777 | PT_CALL( pthread_attr_init( &a)); | 787 | PT_CALL( pthread_attr_init( &a)); |
778 | 788 | ||
@@ -800,7 +810,7 @@ void THREAD_CREATE( THREAD_T* ref, THREAD_RETURN_T (*func)( void*), void* data, | |||
800 | PT_CALL( pthread_attr_setstacksize( &a, _THREAD_STACK_SIZE)); | 810 | PT_CALL( pthread_attr_setstacksize( &a, _THREAD_STACK_SIZE)); |
801 | #endif | 811 | #endif |
802 | 812 | ||
803 | if( !normal) | 813 | if (change_priority) |
804 | { | 814 | { |
805 | struct sched_param sp; | 815 | struct sched_param sp; |
806 | // "The specified scheduling parameters are only used if the scheduling | 816 | // "The specified scheduling parameters are only used if the scheduling |
@@ -816,8 +826,7 @@ void THREAD_CREATE( THREAD_T* ref, THREAD_RETURN_T (*func)( void*), void* data, | |||
816 | 826 | ||
817 | PT_CALL( pthread_attr_setschedpolicy( &a, _PRIO_MODE)); | 827 | PT_CALL( pthread_attr_setschedpolicy( &a, _PRIO_MODE)); |
818 | 828 | ||
819 | // prio range [-3,+3] was checked by the caller | 829 | sp.sched_priority = select_prio(prio); |
820 | sp.sched_priority = gs_prio_remap[ prio + 3]; | ||
821 | PT_CALL( pthread_attr_setschedparam( &a, &sp)); | 830 | PT_CALL( pthread_attr_setschedparam( &a, &sp)); |
822 | } | 831 | } |
823 | 832 | ||
diff --git a/src/threading.h b/src/threading.h index 1224e08..3925076 100644 --- a/src/threading.h +++ b/src/threading.h | |||
@@ -32,8 +32,10 @@ enum e_status { PENDING, RUNNING, WAITING, DONE, ERROR_ST, CANCELLED }; | |||
32 | #define THREADAPI_PTHREAD 2 | 32 | #define THREADAPI_PTHREAD 2 |
33 | 33 | ||
34 | #if( defined( PLATFORM_XBOX) || defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC)) && !defined( HAVE_WIN32_PTHREAD) | 34 | #if( defined( PLATFORM_XBOX) || defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC)) && !defined( HAVE_WIN32_PTHREAD) |
35 | //#pragma message ( "THREADAPI_WINDOWS" ) | ||
35 | #define THREADAPI THREADAPI_WINDOWS | 36 | #define THREADAPI THREADAPI_WINDOWS |
36 | #else // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) | 37 | #else // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) |
38 | //#pragma message ( "THREADAPI_PTHREAD" ) | ||
37 | #define THREADAPI THREADAPI_PTHREAD | 39 | #define THREADAPI THREADAPI_PTHREAD |
38 | #endif // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) | 40 | #endif // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) |
39 | 41 | ||
@@ -169,6 +171,8 @@ bool_t SIGNAL_WAIT( SIGNAL_T *ref, MUTEX_T *mu, time_d timeout ); | |||
169 | /*---=== Threading ===--- | 171 | /*---=== Threading ===--- |
170 | */ | 172 | */ |
171 | 173 | ||
174 | #define THREAD_PRIO_DEFAULT (-999) | ||
175 | |||
172 | #if THREADAPI == THREADAPI_WINDOWS | 176 | #if THREADAPI == THREADAPI_WINDOWS |
173 | 177 | ||
174 | typedef HANDLE THREAD_T; | 178 | typedef HANDLE THREAD_T; |