diff options
| author | Benoit Germain <bnt.germain@gmail.com> | 2018-11-27 15:39:30 +0100 |
|---|---|---|
| committer | Benoit Germain <bnt.germain@gmail.com> | 2018-11-27 15:39:30 +0100 |
| commit | 3aed735e5523af04ff24fd73c4b38944d3ab283d (patch) | |
| tree | c0827580f2885f1ce49f9d20ec96406e53f83976 /src | |
| parent | eae02827ca659a25949c212d8e53dd4334df32d0 (diff) | |
| parent | 0709c08e07e4c5b1696200cd5ee5da0b371e481f (diff) | |
| download | lanes-3aed735e5523af04ff24fd73c4b38944d3ab283d.tar.gz lanes-3aed735e5523af04ff24fd73c4b38944d3ab283d.tar.bz2 lanes-3aed735e5523af04ff24fd73c4b38944d3ab283d.zip | |
Merge branch 'master' of https://github.com/LuaLanes/lanes
Diffstat (limited to 'src')
| -rw-r--r-- | src/lanes.lua | 20 | ||||
| -rw-r--r-- | src/threading.c | 26 | ||||
| -rw-r--r-- | src/threading.h | 2 | ||||
| -rw-r--r-- | src/threading_osx.h | 59 |
4 files changed, 96 insertions, 11 deletions
diff --git a/src/lanes.lua b/src/lanes.lua index 7f2560b..ba9da81 100644 --- a/src/lanes.lua +++ b/src/lanes.lua | |||
| @@ -55,7 +55,7 @@ lanes.configure = function( settings_) | |||
| 55 | end | 55 | end |
| 56 | -- Configure called so remove metatable from lanes | 56 | -- Configure called so remove metatable from lanes |
| 57 | setmetatable( lanes, nil) | 57 | setmetatable( lanes, nil) |
| 58 | -- | 58 | -- |
| 59 | -- Cache globals for code that might run under sandboxing | 59 | -- Cache globals for code that might run under sandboxing |
| 60 | -- | 60 | -- |
| 61 | local assert = assert( assert) | 61 | local assert = assert( assert) |
| @@ -372,7 +372,7 @@ lanes.configure = function( settings_) | |||
| 372 | -- timer tables and sleep in between the timer events. All interaction with | 372 | -- timer tables and sleep in between the timer events. All interaction with |
| 373 | -- the timer lane happens via a 'timer_gateway' Linda, which is common to | 373 | -- the timer lane happens via a 'timer_gateway' Linda, which is common to |
| 374 | -- all that 'require "lanes"'. | 374 | -- all that 'require "lanes"'. |
| 375 | -- | 375 | -- |
| 376 | -- Linda protocol to timer lane: | 376 | -- Linda protocol to timer lane: |
| 377 | -- | 377 | -- |
| 378 | -- TGW_KEY: linda_h, key, [wakeup_at_secs], [repeat_secs] | 378 | -- TGW_KEY: linda_h, key, [wakeup_at_secs], [repeat_secs] |
| @@ -403,7 +403,7 @@ lanes.configure = function( settings_) | |||
| 403 | local timer_body = function() | 403 | local timer_body = function() |
| 404 | set_debug_threadname( "LanesTimer") | 404 | set_debug_threadname( "LanesTimer") |
| 405 | -- | 405 | -- |
| 406 | -- { [deep_linda_lightuserdata]= { [deep_linda_lightuserdata]=linda_h, | 406 | -- { [deep_linda_lightuserdata]= { [deep_linda_lightuserdata]=linda_h, |
| 407 | -- [key]= { wakeup_secs [,period_secs] } [, ...] }, | 407 | -- [key]= { wakeup_secs [,period_secs] } [, ...] }, |
| 408 | -- } | 408 | -- } |
| 409 | -- | 409 | -- |
| @@ -452,7 +452,7 @@ lanes.configure = function( settings_) | |||
| 452 | t1 = { [linda_deep] = linda} -- proxy to use the Linda | 452 | t1 = { [linda_deep] = linda} -- proxy to use the Linda |
| 453 | collection[linda_deep] = t1 | 453 | collection[linda_deep] = t1 |
| 454 | end | 454 | end |
| 455 | 455 | ||
| 456 | if wakeup_at == nil then | 456 | if wakeup_at == nil then |
| 457 | -- Clear the timer | 457 | -- Clear the timer |
| 458 | -- | 458 | -- |
| @@ -482,7 +482,7 @@ lanes.configure = function( settings_) | |||
| 482 | t2= {} | 482 | t2= {} |
| 483 | t1[key]= t2 | 483 | t1[key]= t2 |
| 484 | end | 484 | end |
| 485 | 485 | ||
| 486 | t2[1] = wakeup_at | 486 | t2[1] = wakeup_at |
| 487 | t2[2] = period -- can be 'nil' | 487 | t2[2] = period -- can be 'nil' |
| 488 | end | 488 | end |
| @@ -507,12 +507,12 @@ lanes.configure = function( settings_) | |||
| 507 | local wakeup_at= t2[1] | 507 | local wakeup_at= t2[1] |
| 508 | local period= t2[2] -- may be 'nil' | 508 | local period= t2[2] -- may be 'nil' |
| 509 | 509 | ||
| 510 | if wakeup_at <= now then | 510 | if wakeup_at <= now then |
| 511 | local linda= t1[linda_deep] | 511 | local linda= t1[linda_deep] |
| 512 | assert(linda) | 512 | assert(linda) |
| 513 | 513 | ||
| 514 | linda:set( key, now ) | 514 | linda:set( key, now ) |
| 515 | 515 | ||
| 516 | -- 'pairs()' allows the values to be modified (and even | 516 | -- 'pairs()' allows the values to be modified (and even |
| 517 | -- removed) as far as keys are not touched | 517 | -- removed) as far as keys are not touched |
| 518 | 518 | ||
| @@ -531,10 +531,10 @@ lanes.configure = function( settings_) | |||
| 531 | t2[1]= wakeup_at | 531 | t2[1]= wakeup_at |
| 532 | end | 532 | end |
| 533 | end | 533 | end |
| 534 | 534 | ||
| 535 | if wakeup_at and ((not next_wakeup) or (wakeup_at < next_wakeup)) then | 535 | if wakeup_at and ((not next_wakeup) or (wakeup_at < next_wakeup)) then |
| 536 | next_wakeup= wakeup_at | 536 | next_wakeup= wakeup_at |
| 537 | end | 537 | end |
| 538 | end | 538 | end |
| 539 | end -- t2 loop | 539 | end -- t2 loop |
| 540 | end -- t1 loop | 540 | end -- t1 loop |
diff --git a/src/threading.c b/src/threading.c index c0e6a55..1eab52f 100644 --- a/src/threading.c +++ b/src/threading.c | |||
| @@ -34,6 +34,14 @@ THE SOFTWARE. | |||
| 34 | 34 | ||
| 35 | =============================================================================== | 35 | =============================================================================== |
| 36 | */ | 36 | */ |
| 37 | #if defined(__linux__) | ||
| 38 | # define _GNU_SOURCE /* must be defined before any include */ | ||
| 39 | # ifdef __ANDROID__ | ||
| 40 | # include <android/log.h> | ||
| 41 | # define LOG_TAG "LuaLanes" | ||
| 42 | # endif | ||
| 43 | #endif | ||
| 44 | |||
| 37 | #include <stdio.h> | 45 | #include <stdio.h> |
| 38 | #include <stdlib.h> | 46 | #include <stdlib.h> |
| 39 | #include <assert.h> | 47 | #include <assert.h> |
| @@ -58,6 +66,10 @@ THE SOFTWARE. | |||
| 58 | volatile bool_t sudo; | 66 | volatile bool_t sudo; |
| 59 | #endif | 67 | #endif |
| 60 | 68 | ||
| 69 | #ifdef PLATFORM_OSX | ||
| 70 | # include "threading_osx.h" | ||
| 71 | #endif | ||
| 72 | |||
| 61 | /* Linux with older glibc (such as Debian) don't have pthread_setname_np, but have prctl | 73 | /* Linux with older glibc (such as Debian) don't have pthread_setname_np, but have prctl |
| 62 | */ | 74 | */ |
| 63 | #if defined PLATFORM_LINUX | 75 | #if defined PLATFORM_LINUX |
| @@ -789,7 +801,9 @@ void THREAD_CREATE( THREAD_T* ref, THREAD_RETURN_T (*func)( void*), void* data, | |||
| 789 | // "The specified scheduling parameters are only used if the scheduling | 801 | // "The specified scheduling parameters are only used if the scheduling |
| 790 | // parameter inheritance attribute is PTHREAD_EXPLICIT_SCHED." | 802 | // parameter inheritance attribute is PTHREAD_EXPLICIT_SCHED." |
| 791 | // | 803 | // |
| 804 | #if !defined __ANDROID__ || ( defined __ANDROID__ && __ANDROID_API__ >= 28 ) | ||
| 792 | PT_CALL( pthread_attr_setinheritsched( &a, PTHREAD_EXPLICIT_SCHED)); | 805 | PT_CALL( pthread_attr_setinheritsched( &a, PTHREAD_EXPLICIT_SCHED)); |
| 806 | #endif | ||
| 793 | 807 | ||
| 794 | #ifdef _PRIO_SCOPE | 808 | #ifdef _PRIO_SCOPE |
| 795 | PT_CALL( pthread_attr_setscope( &a, _PRIO_SCOPE)); | 809 | PT_CALL( pthread_attr_setscope( &a, _PRIO_SCOPE)); |
| @@ -884,7 +898,11 @@ void THREAD_SET_AFFINITY( unsigned int aff) | |||
| 884 | ++ bit; | 898 | ++ bit; |
| 885 | aff >>= 1; | 899 | aff >>= 1; |
| 886 | } | 900 | } |
| 901 | #ifdef __ANDROID__ | ||
| 902 | PT_CALL( sched_setaffinity( pthread_self(), sizeof(cpu_set_t), &cpuset)); | ||
| 903 | #else | ||
| 887 | PT_CALL( pthread_setaffinity_np( pthread_self(), sizeof(cpu_set_t), &cpuset)); | 904 | PT_CALL( pthread_setaffinity_np( pthread_self(), sizeof(cpu_set_t), &cpuset)); |
| 905 | #endif | ||
| 888 | } | 906 | } |
| 889 | 907 | ||
| 890 | /* | 908 | /* |
| @@ -955,15 +973,23 @@ bool_t THREAD_WAIT( THREAD_T *ref, double secs , SIGNAL_T *signal_ref, MUTEX_T * | |||
| 955 | } | 973 | } |
| 956 | // | 974 | // |
| 957 | void THREAD_KILL( THREAD_T *ref ) { | 975 | void THREAD_KILL( THREAD_T *ref ) { |
| 976 | #ifdef __ANDROID__ | ||
| 977 | __android_log_print(ANDROID_LOG_WARN, LOG_TAG, "Cannot kill thread!"); | ||
| 978 | #else | ||
| 958 | pthread_cancel( *ref ); | 979 | pthread_cancel( *ref ); |
| 980 | #endif | ||
| 959 | } | 981 | } |
| 960 | 982 | ||
| 961 | void THREAD_MAKE_ASYNCH_CANCELLABLE() | 983 | void THREAD_MAKE_ASYNCH_CANCELLABLE() |
| 962 | { | 984 | { |
| 985 | #ifdef __ANDROID__ | ||
| 986 | __android_log_print(ANDROID_LOG_WARN, LOG_TAG, "Cannot make thread async cancellable!"); | ||
| 987 | #else | ||
| 963 | // that's the default, but just in case... | 988 | // that's the default, but just in case... |
| 964 | pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); | 989 | pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); |
| 965 | // we want cancellation to take effect immediately if possible, instead of waiting for a cancellation point (which is the default) | 990 | // we want cancellation to take effect immediately if possible, instead of waiting for a cancellation point (which is the default) |
| 966 | pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NULL); | 991 | pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NULL); |
| 992 | #endif | ||
| 967 | } | 993 | } |
| 968 | 994 | ||
| 969 | void THREAD_SETNAME( char const* _name) | 995 | void THREAD_SETNAME( char const* _name) |
diff --git a/src/threading.h b/src/threading.h index 8ebe805..063cc82 100644 --- a/src/threading.h +++ b/src/threading.h | |||
| @@ -143,7 +143,7 @@ enum e_status { PENDING, RUNNING, WAITING, DONE, ERROR_ST, CANCELLED }; | |||
| 143 | // | 143 | // |
| 144 | #if defined( PLATFORM_OSX) | 144 | #if defined( PLATFORM_OSX) |
| 145 | #define YIELD() pthread_yield_np() | 145 | #define YIELD() pthread_yield_np() |
| 146 | #elif defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC) // no PTHREAD for PLATFORM_XBOX | 146 | #elif defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC) || defined(__ANDROID__) // no PTHREAD for PLATFORM_XBOX |
| 147 | // for some reason win32-pthread doesn't have pthread_yield(), but sched_yield() | 147 | // for some reason win32-pthread doesn't have pthread_yield(), but sched_yield() |
| 148 | #define YIELD() sched_yield() | 148 | #define YIELD() sched_yield() |
| 149 | #else | 149 | #else |
diff --git a/src/threading_osx.h b/src/threading_osx.h new file mode 100644 index 0000000..93da8c3 --- /dev/null +++ b/src/threading_osx.h | |||
| @@ -0,0 +1,59 @@ | |||
| 1 | /* | ||
| 2 | * THREADING_OSX.H | ||
| 3 | * http://yyshen.github.io/2015/01/18/binding_threads_to_cores_osx.html | ||
| 4 | */ | ||
| 5 | #ifndef __threading_osx_h__ | ||
| 6 | #define __threading_osx_h__ 1 | ||
| 7 | |||
| 8 | #include <mach/mach_types.h> | ||
| 9 | #include <mach/thread_act.h> | ||
| 10 | #include <sys/sysctl.h> | ||
| 11 | |||
| 12 | #define SYSCTL_CORE_COUNT "machdep.cpu.core_count" | ||
| 13 | |||
| 14 | typedef struct cpu_set { | ||
| 15 | uint32_t count; | ||
| 16 | } cpu_set_t; | ||
| 17 | |||
| 18 | static inline void CPU_ZERO(cpu_set_t *cs) { cs->count = 0; } | ||
| 19 | static inline void CPU_SET(int num, cpu_set_t *cs) { cs->count |= (1 << num); } | ||
| 20 | static inline int CPU_ISSET(int num, cpu_set_t *cs) { return (cs->count & (1 << num)); } | ||
| 21 | |||
| 22 | int sched_getaffinity(pid_t pid, size_t cpu_size, cpu_set_t *cpu_set) | ||
| 23 | { | ||
| 24 | int32_t core_count = 0; | ||
| 25 | size_t len = sizeof(core_count); | ||
| 26 | int ret = sysctlbyname(SYSCTL_CORE_COUNT, &core_count, &len, 0, 0); | ||
| 27 | if (ret) | ||
| 28 | { | ||
| 29 | // printf("error while get core count %d\n", ret); | ||
| 30 | return -1; | ||
| 31 | } | ||
| 32 | cpu_set->count = 0; | ||
| 33 | for (int i = 0; i < core_count; i++) | ||
| 34 | { | ||
| 35 | cpu_set->count |= (1 << i); | ||
| 36 | } | ||
| 37 | |||
| 38 | return 0; | ||
| 39 | } | ||
| 40 | |||
| 41 | int pthread_setaffinity_np(pthread_t thread, size_t cpu_size, cpu_set_t *cpu_set) | ||
| 42 | { | ||
| 43 | thread_port_t mach_thread; | ||
| 44 | int core = 0; | ||
| 45 | |||
| 46 | for (core = 0; core < 8 * cpu_size; core++) | ||
| 47 | { | ||
| 48 | if (CPU_ISSET(core, cpu_set)) | ||
| 49 | break; | ||
| 50 | } | ||
| 51 | // printf("binding to core %d\n", core); | ||
| 52 | thread_affinity_policy_data_t policy = { core }; | ||
| 53 | mach_thread = pthread_mach_thread_np(thread); | ||
| 54 | thread_policy_set(mach_thread, THREAD_AFFINITY_POLICY, (thread_policy_t)&policy, 1); | ||
| 55 | |||
| 56 | return 0; | ||
| 57 | } | ||
| 58 | |||
| 59 | #endif | ||
