aboutsummaryrefslogtreecommitdiff
path: root/src/threading.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/threading.c')
-rw-r--r--src/threading.c108
1 files changed, 67 insertions, 41 deletions
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{