aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoit Germain <benoit.germain@ubisoft.com>2023-07-28 14:48:16 +0200
committerBenoit Germain <benoit.germain@ubisoft.com>2023-07-28 14:48:16 +0200
commitd73f4cee37b0a43edadf9709289798ee4bfccc0e (patch)
tree8c5ce974f9b148e343756d7c667125bee7b22351
parent886eb0365f38d455ca2c9ff8dd3ddf12fedb6960 (diff)
downloadlanes-d73f4cee37b0a43edadf9709289798ee4bfccc0e.tar.gz
lanes-d73f4cee37b0a43edadf9709289798ee4bfccc0e.tar.bz2
lanes-d73f4cee37b0a43edadf9709289798ee4bfccc0e.zip
tweaks to linux thread priority management
-rw-r--r--CHANGES6
-rw-r--r--src/lanes.c77
-rw-r--r--src/threading.c137
-rw-r--r--src/threading.h4
4 files changed, 122 insertions, 102 deletions
diff --git a/CHANGES b/CHANGES
index 568f6db..3b333b2 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,11 @@
1CHANGES: 1CHANGES:
2 2
3CHANGE 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
6CHANGE 154: eligovision 1-Mar-22
7 * Fix 3-parametrized __lanesclone
8
3CHANGE 153: BGe 17-Feb-22 9CHANGE 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
770static 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
767void THREAD_CREATE( THREAD_T* ref, THREAD_RETURN_T (*func)( void*), void* data, int prio /* -3..+3 */) 778void 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;