aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoit Germain <bnt.germain@gmail.com>2018-11-27 15:39:30 +0100
committerBenoit Germain <bnt.germain@gmail.com>2018-11-27 15:39:30 +0100
commit3aed735e5523af04ff24fd73c4b38944d3ab283d (patch)
treec0827580f2885f1ce49f9d20ec96406e53f83976
parenteae02827ca659a25949c212d8e53dd4334df32d0 (diff)
parent0709c08e07e4c5b1696200cd5ee5da0b371e481f (diff)
downloadlanes-3aed735e5523af04ff24fd73c4b38944d3ab283d.tar.gz
lanes-3aed735e5523af04ff24fd73c4b38944d3ab283d.tar.bz2
lanes-3aed735e5523af04ff24fd73c4b38944d3ab283d.zip
Merge branch 'master' of https://github.com/LuaLanes/lanes
-rw-r--r--src/lanes.lua20
-rw-r--r--src/threading.c26
-rw-r--r--src/threading.h2
-rw-r--r--src/threading_osx.h59
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
14typedef struct cpu_set {
15 uint32_t count;
16} cpu_set_t;
17
18static inline void CPU_ZERO(cpu_set_t *cs) { cs->count = 0; }
19static inline void CPU_SET(int num, cpu_set_t *cs) { cs->count |= (1 << num); }
20static inline int CPU_ISSET(int num, cpu_set_t *cs) { return (cs->count & (1 << num)); }
21
22int 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
41int 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