diff options
Diffstat (limited to 'src/threading.c')
-rw-r--r-- | src/threading.c | 108 |
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 | ||
14 | Copyright (C) 2007-10 Asko Kauppi <akauppi@gmail.com> | 14 | Copyright (C) 2007-10 Asko Kauppi <akauppi@gmail.com> |
15 | Copyright (C) 2009-13, Benoit Germain <bnt.germain@gmail.com> | ||
15 | 16 | ||
16 | Permission is hereby granted, free of charge, to any person obtaining a copy | 17 | Permission is hereby granted, free of charge, to any person obtaining a copy |
17 | of this software and associated documentation files (the "Software"), to deal | 18 | of 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 | 273 | static 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, | 286 | MSDN: "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 | ); | 289 | void 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 | |||
309 | void 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 | |||
306 | bool_t THREAD_WAIT_IMPL( THREAD_T *ref, double secs) | 319 | bool_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 | // | 733 | void THREAD_CREATE( THREAD_T* ref, THREAD_RETURN_T (*func)( void*), void* data, int prio /* -3..+3 */) |
721 | void 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 | |||
843 | void 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 | */ |
839 | bool_t THREAD_WAIT( THREAD_T *ref, double secs , SIGNAL_T *signal_ref, MUTEX_T *mu_ref, volatile enum e_status *st_ref) | 865 | bool_t THREAD_WAIT( THREAD_T *ref, double secs , SIGNAL_T *signal_ref, MUTEX_T *mu_ref, volatile enum e_status *st_ref) |
840 | { | 866 | { |