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 | |
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
-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 | ||