aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBenoit Germain <b n t DOT g e r m a i n AT g m a i l DOT c o m>2013-12-04 08:40:23 +0100
committerBenoit Germain <b n t DOT g e r m a i n AT g m a i l DOT c o m>2013-12-04 08:40:23 +0100
commit49f8b961cc230280e4cf86cc8d50c8a6d8687a65 (patch)
tree9b096414f00dc12a3893158622e150c7085b0599 /src
parent653dff5dc2c1a5764ef1afb6ffa5dd96758865ea (diff)
downloadlanes-49f8b961cc230280e4cf86cc8d50c8a6d8687a65.tar.gz
lanes-49f8b961cc230280e4cf86cc8d50c8a6d8687a65.tar.bz2
lanes-49f8b961cc230280e4cf86cc8d50c8a6d8687a65.zip
new API lanes.set_thread_priority()
Diffstat (limited to 'src')
-rw-r--r--src/lanes.c31
-rw-r--r--src/lanes.lua1
-rw-r--r--src/threading.c108
-rw-r--r--src/threading.h84
4 files changed, 133 insertions, 91 deletions
diff --git a/src/lanes.c b/src/lanes.c
index ec7fd9e..467c920 100644
--- a/src/lanes.c
+++ b/src/lanes.c
@@ -35,10 +35,10 @@
35 * 35 *
36 * Defines: 36 * Defines:
37 * -DLINUX_SCHED_RR: all threads are lifted to SCHED_RR category, to 37 * -DLINUX_SCHED_RR: all threads are lifted to SCHED_RR category, to
38 * allow negative priorities (-2,-1) be used. Even without this, 38 * allow negative priorities [-3,-1] be used. Even without this,
39 * using priorities will require 'sudo' privileges on Linux. 39 * using priorities will require 'sudo' privileges on Linux.
40 * 40 *
41 * -DUSE_PTHREAD_TIMEDJOIN: use 'pthread_timedjoin_np()' for waiting 41 * -DUSE_PTHREAD_TIMEDJOIN: use 'pthread_timedjoin_np()' for waiting
42 * for threads with a timeout. This changes the thread cleanup 42 * for threads with a timeout. This changes the thread cleanup
43 * mechanism slightly (cleans up at the join, not once the thread 43 * mechanism slightly (cleans up at the join, not once the thread
44 * has finished). May or may not be a good idea to use it. 44 * has finished). May or may not be a good idea to use it.
@@ -52,7 +52,7 @@
52 * ... 52 * ...
53 */ 53 */
54 54
55char const* VERSION = "3.7.3"; 55char const* VERSION = "3.7.4";
56 56
57/* 57/*
58=============================================================================== 58===============================================================================
@@ -1734,6 +1734,20 @@ LUAG_FUNC( set_debug_threadname)
1734 return 0; 1734 return 0;
1735} 1735}
1736 1736
1737LUAG_FUNC( set_thread_priority)
1738{
1739 int const prio = luaL_checkint( L, 1);
1740 // public Lanes API accepts a generic range -3/+3
1741 // that will be remapped into the platform-specific scheduler priority scheme
1742 // On some platforms, -3 is equivalent to -2 and +3 to +2
1743 if( prio < THREAD_PRIO_MIN || prio > THREAD_PRIO_MAX)
1744 {
1745 return luaL_error( L, "priority out of range: %d..+%d (%d)", THREAD_PRIO_MIN, THREAD_PRIO_MAX, prio);
1746 }
1747 THREAD_SET_PRIORITY( prio);
1748 return 0;
1749}
1750
1737#if USE_DEBUG_SPEW 1751#if USE_DEBUG_SPEW
1738// can't use direct LUA_x errcode indexing because the sequence is not the same between Lua 5.1 and 5.2 :-( 1752// can't use direct LUA_x errcode indexing because the sequence is not the same between Lua 5.1 and 5.2 :-(
1739// LUA_ERRERR doesn't have the same value 1753// LUA_ERRERR doesn't have the same value
@@ -2693,6 +2707,7 @@ static const struct luaL_Reg lanes_functions [] = {
2693 {"linda", LG_linda}, 2707 {"linda", LG_linda},
2694 {"now_secs", LG_now_secs}, 2708 {"now_secs", LG_now_secs},
2695 {"wakeup_conv", LG_wakeup_conv}, 2709 {"wakeup_conv", LG_wakeup_conv},
2710 {"set_thread_priority", LG_set_thread_priority},
2696 {"nameof", luaG_nameof}, 2711 {"nameof", luaG_nameof},
2697 {"set_singlethreaded", LG_set_singlethreaded}, 2712 {"set_singlethreaded", LG_set_singlethreaded},
2698 {NULL, NULL} 2713 {NULL, NULL}
@@ -2754,16 +2769,18 @@ static void init_once_LOCKED( lua_State* L)
2754 // be enabled also for Linux. 2769 // be enabled also for Linux.
2755 // 2770 //
2756#ifdef PLATFORM_LINUX 2771#ifdef PLATFORM_LINUX
2757 sudo= geteuid()==0; // we are root? 2772 sudo = (geteuid() == 0); // we are root?
2758 2773
2759 // If lower priorities (-2..-1) are wanted, we need to lift the main 2774 // If lower priorities (-2..-1) are wanted, we need to lift the main
2760 // thread to SCHED_RR and 50 (medium) level. Otherwise, we're always below 2775 // thread to SCHED_RR and 50 (medium) level. Otherwise, we're always below
2761 // the launched threads (even -2). 2776 // the launched threads (even -2).
2762 // 2777 //
2763#ifdef LINUX_SCHED_RR 2778#ifdef LINUX_SCHED_RR
2764 if (sudo) { 2779 if( sudo)
2765 struct sched_param sp= {0}; sp.sched_priority= _PRIO_0; 2780 {
2766 PT_CALL( pthread_setschedparam( pthread_self(), SCHED_RR, &sp) ); 2781 struct sched_param sp;
2782 sp.sched_priority = _PRIO_0;
2783 PT_CALL( pthread_setschedparam( pthread_self(), SCHED_RR, &sp));
2767 } 2784 }
2768#endif // LINUX_SCHED_RR 2785#endif // LINUX_SCHED_RR
2769#endif // PLATFORM_LINUX 2786#endif // PLATFORM_LINUX
diff --git a/src/lanes.lua b/src/lanes.lua
index 1b81944..6e2a736 100644
--- a/src/lanes.lua
+++ b/src/lanes.lua
@@ -683,6 +683,7 @@ end
683 lanes.cancel_error = core.cancel_error 683 lanes.cancel_error = core.cancel_error
684 lanes.nameof = core.nameof 684 lanes.nameof = core.nameof
685 lanes.threads = core.threads or function() error "lane tracking is not available" end -- core.threads isn't registered if settings.track_lanes is false 685 lanes.threads = core.threads or function() error "lane tracking is not available" end -- core.threads isn't registered if settings.track_lanes is false
686 lanes.set_thread_priority = core.set_thread_priority
686 lanes.timer = timer 687 lanes.timer = timer
687 lanes.timer_lane = timer_lane 688 lanes.timer_lane = timer_lane
688 lanes.timers = timers 689 lanes.timers = timers
diff --git a/src/threading.c b/src/threading.c
index 18eef87..db9f734 100644
--- a/src/threading.c
+++ b/src/threading.c
@@ -12,6 +12,7 @@
12=============================================================================== 12===============================================================================
13 13
14Copyright (C) 2007-10 Asko Kauppi <akauppi@gmail.com> 14Copyright (C) 2007-10 Asko Kauppi <akauppi@gmail.com>
15Copyright (C) 2009-13, Benoit Germain <bnt.germain@gmail.com>
15 16
16Permission is hereby granted, free of charge, to any person obtaining a copy 17Permission is hereby granted, free of charge, to any person obtaining a copy
17of this software and associated documentation files (the "Software"), to deal 18of this software and associated documentation files (the "Software"), to deal
@@ -269,40 +270,52 @@ static void prepare_timeout( struct timespec *ts, time_d abs_secs ) {
269 } 270 }
270#endif // Windows NT4 271#endif // Windows NT4
271 272
272 /* MSDN: "If you would like to use the CRT in ThreadProc, use the 273static int const gs_prio_remap[] =
273 _beginthreadex function instead (of CreateThread)." 274{
274 MSDN: "you can create at most 2028 threads" 275 THREAD_PRIORITY_IDLE,
275 */ 276 THREAD_PRIORITY_LOWEST,
276 void 277 THREAD_PRIORITY_BELOW_NORMAL,
277 THREAD_CREATE( THREAD_T *ref, 278 THREAD_PRIORITY_NORMAL,
278 THREAD_RETURN_T (__stdcall *func)( void * ), 279 THREAD_PRIORITY_ABOVE_NORMAL,
279 // Note: Visual C++ requires '__stdcall' where it is 280 THREAD_PRIORITY_HIGHEST,
280 void *data, int prio /* -3..+3 */ ) { 281 THREAD_PRIORITY_TIME_CRITICAL
281 282};
282 HANDLE h= (HANDLE)_beginthreadex( NULL, // security 283
283 _THREAD_STACK_SIZE, 284/* MSDN: "If you would like to use the CRT in ThreadProc, use the
284 func, 285_beginthreadex function instead (of CreateThread)."
285 data, 286MSDN: "you can create at most 2028 threads"
286 0, // flags (0/CREATE_SUSPENDED) 287*/
287 NULL // thread id (not used) 288// Note: Visual C++ requires '__stdcall' where it is
288 ); 289void THREAD_CREATE( THREAD_T* ref, THREAD_RETURN_T (__stdcall *func)( void*), void* data, int prio /* -3..+3 */)
289 290{
290 if (h == INVALID_HANDLE_VALUE) FAIL( "CreateThread", GetLastError() ); 291 HANDLE h = (HANDLE) _beginthreadex( NULL, // security
291 292 _THREAD_STACK_SIZE,
292 if (prio!= 0) { 293 func,
293 int win_prio= (prio == +3) ? THREAD_PRIORITY_TIME_CRITICAL : 294 data,
294 (prio == +2) ? THREAD_PRIORITY_HIGHEST : 295 0, // flags (0/CREATE_SUSPENDED)
295 (prio == +1) ? THREAD_PRIORITY_ABOVE_NORMAL : 296 NULL // thread id (not used)
296 (prio == -1) ? THREAD_PRIORITY_BELOW_NORMAL : 297 );
297 (prio == -2) ? THREAD_PRIORITY_LOWEST : 298
298 THREAD_PRIORITY_IDLE; // -3 299 if( h == INVALID_HANDLE_VALUE)
299 300 FAIL( "CreateThread", GetLastError());
300 if (!SetThreadPriority( h, win_prio )) 301
301 FAIL( "SetThreadPriority", GetLastError() ); 302 if (!SetThreadPriority( h, gs_prio_remap[prio + 3]))
302 } 303 FAIL( "SetThreadPriority", GetLastError());
303 *ref= h; 304
304 } 305 *ref = h;
305 // 306}
307
308
309void THREAD_SET_PRIORITY( int prio)
310{
311 // prio range [-3,+3] was checked by the caller
312 if (!SetThreadPriority( GetCurrentThread(), gs_prio_remap[prio + 3]))
313 {
314 FAIL( "THREAD_SET_PRIORITY", GetLastError());
315 }
316}
317
318
306bool_t THREAD_WAIT_IMPL( THREAD_T *ref, double secs) 319bool_t THREAD_WAIT_IMPL( THREAD_T *ref, double secs)
307{ 320{
308 DWORD ms = (secs<0.0) ? INFINITE : (DWORD)((secs*1000.0)+0.5); 321 DWORD ms = (secs<0.0) ? INFINITE : (DWORD)((secs*1000.0)+0.5);
@@ -710,20 +723,19 @@ static int const gs_prio_remap[] =
710# endif 723# endif
711 724
712#if defined _PRIO_0 725#if defined _PRIO_0
713# define _PRIO_AN (_PRIO_0 + ((_PRIO_HI-_PRIO_0)/2) ) 726# define _PRIO_AN (_PRIO_0 + ((_PRIO_HI-_PRIO_0)/2))
714# define _PRIO_BN (_PRIO_LO + ((_PRIO_0-_PRIO_LO)/2) ) 727# define _PRIO_BN (_PRIO_LO + ((_PRIO_0-_PRIO_LO)/2))
715 728
716 _PRIO_LO, _PRIO_LO, _PRIO_BN, _PRIO_0, _PRIO_AN, _PRIO_HI, _PRIO_HI 729 _PRIO_LO, _PRIO_LO, _PRIO_BN, _PRIO_0, _PRIO_AN, _PRIO_HI, _PRIO_HI
717#endif // _PRIO_0 730#endif // _PRIO_0
718}; 731};
719 732
720// 733void THREAD_CREATE( THREAD_T* ref, THREAD_RETURN_T (*func)( void*), void* data, int prio /* -3..+3 */)
721void THREAD_CREATE( THREAD_T* ref, THREAD_RETURN_T (*func)( void * ), void *data, int prio /* -2..+2 */)
722{ 734{
723 pthread_attr_t a; 735 pthread_attr_t a;
724 bool_t const normal = 736 bool_t const normal =
725#if defined(PLATFORM_LINUX) && defined(LINUX_SCHED_RR) 737#if defined(PLATFORM_LINUX) && defined(LINUX_SCHED_RR)
726 !sudo; // with sudo, even normal thread must use SCHED_RR 738 !sudo; // with sudo, even normal thread must use SCHED_RR
727#else 739#else
728 (prio == 0); 740 (prio == 0);
729#endif 741#endif
@@ -762,7 +774,6 @@ void THREAD_CREATE( THREAD_T* ref, THREAD_RETURN_T (*func)( void * ), void *data
762 // 774 //
763 PT_CALL( pthread_attr_setinheritsched( &a, PTHREAD_EXPLICIT_SCHED)); 775 PT_CALL( pthread_attr_setinheritsched( &a, PTHREAD_EXPLICIT_SCHED));
764 776
765
766#ifdef _PRIO_SCOPE 777#ifdef _PRIO_SCOPE
767 PT_CALL( pthread_attr_setscope( &a, _PRIO_SCOPE)); 778 PT_CALL( pthread_attr_setscope( &a, _PRIO_SCOPE));
768#endif // _PRIO_SCOPE 779#endif // _PRIO_SCOPE
@@ -828,13 +839,28 @@ void THREAD_CREATE( THREAD_T* ref, THREAD_RETURN_T (*func)( void * ), void *data
828 PT_CALL( pthread_attr_destroy( &a)); 839 PT_CALL( pthread_attr_destroy( &a));
829} 840}
830 841
842
843void THREAD_SET_PRIORITY( int prio)
844{
845#if defined PLATFORM_LINUX && defined LINUX_SCHED_RR
846 if( sudo) // only root-privileged process can change priorities
847#endif // defined PLATFORM_LINUX && defined LINUX_SCHED_RR
848 {
849 struct sched_param sp;
850 // prio range [-3,+3] was checked by the caller
851 sp.sched_priority = gs_prio_remap[ prio + 3];
852 PT_CALL( pthread_setschedparam( pthread_self(), _PRIO_MODE, &sp));
853 }
854}
855
856
831 /* 857 /*
832 * Wait for a thread to finish. 858 * Wait for a thread to finish.
833 * 859 *
834 * 'mu_ref' is a lock we should use for the waiting; initially unlocked. 860 * 'mu_ref' is a lock we should use for the waiting; initially unlocked.
835 * Same lock as passed to THREAD_EXIT. 861 * Same lock as passed to THREAD_EXIT.
836 * 862 *
837 * Returns TRUE for succesful wait, FALSE for timed out 863 * Returns TRUE for successful wait, FALSE for timed out
838 */ 864 */
839bool_t THREAD_WAIT( THREAD_T *ref, double secs , SIGNAL_T *signal_ref, MUTEX_T *mu_ref, volatile enum e_status *st_ref) 865bool_t THREAD_WAIT( THREAD_T *ref, double secs , SIGNAL_T *signal_ref, MUTEX_T *mu_ref, volatile enum e_status *st_ref)
840{ 866{
diff --git a/src/threading.h b/src/threading.h
index d87bba6..0698355 100644
--- a/src/threading.h
+++ b/src/threading.h
@@ -184,26 +184,25 @@ bool_t SIGNAL_WAIT( SIGNAL_T *ref, MUTEX_T *mu, time_d timeout );
184 184
185#if THREADAPI == THREADAPI_WINDOWS 185#if THREADAPI == THREADAPI_WINDOWS
186 186
187 typedef HANDLE THREAD_T; 187 typedef HANDLE THREAD_T;
188# define THREAD_ISNULL( _h) (_h == 0) 188# define THREAD_ISNULL( _h) (_h == 0)
189 // 189 void THREAD_CREATE( THREAD_T* ref, THREAD_RETURN_T (__stdcall *func)( void*), void* data, int prio /* -3..+3 */);
190 void THREAD_CREATE( THREAD_T *ref,
191 THREAD_RETURN_T (__stdcall *func)( void * ),
192 void *data, int prio /* -3..+3 */ );
193 190
194# define THREAD_PRIO_MIN (-3) 191# define THREAD_PRIO_MIN (-3)
195# define THREAD_PRIO_MAX (+3) 192# define THREAD_PRIO_MAX (+3)
196 193
197#define THREAD_CLEANUP_PUSH( cb_, val_) 194# define THREAD_CLEANUP_PUSH( cb_, val_)
198#define THREAD_CLEANUP_POP( execute_) 195# define THREAD_CLEANUP_POP( execute_)
199 196
200#else // THREADAPI == THREADAPI_PTHREAD 197#else // THREADAPI == THREADAPI_PTHREAD
201 /* Platforms that have a timed 'pthread_join()' can get away with a simpler 198
202 * implementation. Others will use a condition variable. 199 /* Platforms that have a timed 'pthread_join()' can get away with a simpler
203 */ 200 * implementation. Others will use a condition variable.
204#if defined __WINPTHREADS_VERSION 201 */
205//#define USE_PTHREAD_TIMEDJOIN 202# if defined __WINPTHREADS_VERSION
206#endif // __WINPTHREADS_VERSION 203//# define USE_PTHREAD_TIMEDJOIN
204# endif // __WINPTHREADS_VERSION
205
207# ifdef USE_PTHREAD_TIMEDJOIN 206# ifdef USE_PTHREAD_TIMEDJOIN
208# ifdef PLATFORM_OSX 207# ifdef PLATFORM_OSX
209# error "No 'pthread_timedjoin()' on this system" 208# error "No 'pthread_timedjoin()' on this system"
@@ -213,33 +212,31 @@ bool_t SIGNAL_WAIT( SIGNAL_T *ref, MUTEX_T *mu, time_d timeout );
213# endif 212# endif
214# endif 213# endif
215 214
216 typedef pthread_t THREAD_T; 215 typedef pthread_t THREAD_T;
217# define THREAD_ISNULL( _h) 0 // pthread_t may be a structure: never 'null' by itself 216# define THREAD_ISNULL( _h) 0 // pthread_t may be a structure: never 'null' by itself
218 217
219 void THREAD_CREATE( THREAD_T *ref, 218 void THREAD_CREATE( THREAD_T* ref, THREAD_RETURN_T (*func)( void*), void* data, int prio /* -3..+3 */);
220 THREAD_RETURN_T (*func)( void * ), 219
221 void *data, int prio /* -2..+2 */ ); 220# if defined(PLATFORM_LINUX)
222 221 extern volatile bool_t sudo;
223# if defined(PLATFORM_LINUX) 222# ifdef LINUX_SCHED_RR
224 extern volatile bool_t sudo; 223# define THREAD_PRIO_MIN (sudo ? -3 : 0)
225# ifdef LINUX_SCHED_RR 224# else
226# define THREAD_PRIO_MIN (sudo ? -3 : 0) 225# define THREAD_PRIO_MIN (0)
227# else 226# endif
228# define THREAD_PRIO_MIN (0) 227# define THREAD_PRIO_MAX (sudo ? +3 : 0)
229# endif 228# else
230# define THREAD_PRIO_MAX (sudo ? +3 : 0) 229# define THREAD_PRIO_MIN (-3)
231# else 230# define THREAD_PRIO_MAX (+3)
232# define THREAD_PRIO_MIN (-3) 231# endif
233# define THREAD_PRIO_MAX (+3) 232
234# endif 233# if THREADWAIT_METHOD == THREADWAIT_CONDVAR
235 234# define THREAD_CLEANUP_PUSH( cb_, val_) pthread_cleanup_push( cb_, val_)
236#if THREADWAIT_METHOD == THREADWAIT_CONDVAR 235# define THREAD_CLEANUP_POP( execute_) pthread_cleanup_pop( execute_)
237#define THREAD_CLEANUP_PUSH( cb_, val_) pthread_cleanup_push( cb_, val_) 236# else
238#define THREAD_CLEANUP_POP( execute_) pthread_cleanup_pop( execute_) 237# define THREAD_CLEANUP_PUSH( cb_, val_) {
239#else 238# define THREAD_CLEANUP_POP( execute_) }
240#define THREAD_CLEANUP_PUSH( cb_, val_) { 239# endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR
241#define THREAD_CLEANUP_POP( execute_) }
242#endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR
243#endif // THREADAPI == THREADAPI_WINDOWS 240#endif // THREADAPI == THREADAPI_WINDOWS
244 241
245/* 242/*
@@ -267,5 +264,6 @@ bool_t THREAD_WAIT_IMPL( THREAD_T *ref, double secs, SIGNAL_T *signal_ref, MUTEX
267void THREAD_KILL( THREAD_T* ref); 264void THREAD_KILL( THREAD_T* ref);
268void THREAD_SETNAME( char const* _name); 265void THREAD_SETNAME( char const* _name);
269void THREAD_MAKE_ASYNCH_CANCELLABLE(); 266void THREAD_MAKE_ASYNCH_CANCELLABLE();
267void THREAD_SET_PRIORITY( int prio);
270 268
271#endif // __threading_h__ 269#endif // __threading_h__