diff --git a/ractor.h b/ractor.h index 4cd89522a7..d3de06b559 100644 --- a/ractor.h +++ b/ractor.h @@ -205,7 +205,15 @@ rb_ractor_thread_switch(rb_ractor_t *cr, rb_thread_t *th) static inline void rb_ractor_set_current_ec(rb_ractor_t *cr, rb_execution_context_t *ec) { +#ifdef RB_THREAD_LOCAL_SPECIFIER + #if __APPLE__ + rb_current_ec_set(ec); + #else + ruby_current_ec = ec; + #endif +#else native_tls_set(ruby_current_ec_key, ec); +#endif if (cr->threads.running_ec != ec) { if (0) fprintf(stderr, "rb_ractor_set_current_ec ec:%p->%p\n", diff --git a/thread_pthread.c b/thread_pthread.c index 427897cfd8..71667aec69 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -550,7 +550,11 @@ native_cond_timeout(rb_nativethread_cond_t *cond, const rb_hrtime_t rel) #define native_cleanup_push pthread_cleanup_push #define native_cleanup_pop pthread_cleanup_pop +#ifdef RB_THREAD_LOCAL_SPECIFIER +static RB_THREAD_LOCAL_SPECIFIER rb_thread_t *ruby_native_thread; +#else static pthread_key_t ruby_native_thread_key; +#endif static void null_func(int i) @@ -561,7 +565,11 @@ null_func(int i) static rb_thread_t * ruby_thread_from_native(void) { +#ifdef RB_THREAD_LOCAL_SPECIFIER + return ruby_native_thread; +#else return pthread_getspecific(ruby_native_thread_key); +#endif } static int @@ -570,7 +578,12 @@ ruby_thread_set_native(rb_thread_t *th) if (th && th->ec) { rb_ractor_set_current_ec(th->ractor, th->ec); } +#ifdef RB_THREAD_LOCAL_SPECIFIER + ruby_native_thread = th; + return 1; +#else return pthread_setspecific(ruby_native_thread_key, th) == 0; +#endif } static void native_thread_init(rb_thread_t *th); @@ -587,12 +600,15 @@ Init_native_thread(rb_thread_t *th) if (r) condattr_monotonic = NULL; } #endif + +#ifndef RB_THREAD_LOCAL_SPECIFIER if (pthread_key_create(&ruby_native_thread_key, 0) == EAGAIN) { rb_bug("pthread_key_create failed (ruby_native_thread_key)"); } if (pthread_key_create(&ruby_current_ec_key, 0) == EAGAIN) { rb_bug("pthread_key_create failed (ruby_current_ec_key)"); } +#endif th->thread_id = pthread_self(); ruby_thread_set_native(th); fill_thread_id_str(th); diff --git a/thread_pthread.h b/thread_pthread.h index d14857b05a..fa375b3e55 100644 --- a/thread_pthread.h +++ b/thread_pthread.h @@ -83,6 +83,14 @@ typedef struct rb_global_vm_lock_struct { int wait_yield; } rb_global_vm_lock_t; + +#if __STDC_VERSION__ >= 201112 + #define RB_THREAD_LOCAL_SPECIFIER _Thread_local +#elif defined(__GNUC__) + /* note that ICC (linux) and Clang are covered by __GNUC__ */ + #define RB_THREAD_LOCAL_SPECIFIER __thread +#else + typedef pthread_key_t native_tls_key_t; static inline void * @@ -102,5 +110,20 @@ native_tls_set(native_tls_key_t key, void *ptr) rb_bug("pthread_setspecific error"); } } +#endif + +RUBY_SYMBOL_EXPORT_BEGIN +#ifdef RB_THREAD_LOCAL_SPECIFIER + #if __APPLE__ + // on Darwin, TLS can not be accessed across .so + struct rb_execution_context_struct *rb_current_ec(); + void rb_current_ec_set(struct rb_execution_context_struct *); + #else + RUBY_EXTERN RB_THREAD_LOCAL_SPECIFIER struct rb_execution_context_struct *ruby_current_ec; + #endif +#else + RUBY_EXTERN native_tls_key_t ruby_current_ec_key; +#endif +RUBY_SYMBOL_EXPORT_END #endif /* RUBY_THREAD_PTHREAD_H */ diff --git a/thread_win32.h b/thread_win32.h index 0d95731587..cdcc159b2d 100644 --- a/thread_win32.h +++ b/thread_win32.h @@ -63,4 +63,8 @@ void rb_native_cond_timedwait(rb_nativethread_cond_t *cond, rb_nativethread_lock void rb_native_cond_initialize(rb_nativethread_cond_t *cond); void rb_native_cond_destroy(rb_nativethread_cond_t *cond); +RUBY_SYMBOL_EXPORT_BEGIN +RUBY_EXTERN native_tls_key_t ruby_current_ec_key; +RUBY_SYMBOL_EXPORT_END + #endif /* RUBY_THREAD_WIN32_H */ diff --git a/vm.c b/vm.c index 77a0659dd1..879814a14b 100644 --- a/vm.c +++ b/vm.c @@ -379,7 +379,26 @@ VALUE rb_block_param_proxy; #define ruby_vm_redefined_flag GET_VM()->redefined_flag VALUE ruby_vm_const_missing_count = 0; rb_vm_t *ruby_current_vm_ptr = NULL; + +#ifdef RB_THREAD_LOCAL_SPECIFIER +RB_THREAD_LOCAL_SPECIFIER rb_execution_context_t *ruby_current_ec; + +#ifdef __APPLE__ + rb_execution_context_t * + rb_current_ec(void) + { + return ruby_current_ec; + } + void + rb_current_ec_set(rb_execution_context_t *ec) + { + ruby_current_ec = ec; + } +#endif + +#else native_tls_key_t ruby_current_ec_key; +#endif rb_event_flag_t ruby_vm_event_flags; rb_event_flag_t ruby_vm_event_enabled_global_flags; diff --git a/vm_core.h b/vm_core.h index 73b6be52f6..f644e8a6bc 100644 --- a/vm_core.h +++ b/vm_core.h @@ -1721,8 +1721,6 @@ RUBY_EXTERN rb_event_flag_t ruby_vm_event_flags; RUBY_EXTERN rb_event_flag_t ruby_vm_event_enabled_global_flags; RUBY_EXTERN unsigned int ruby_vm_event_local_num; -RUBY_EXTERN native_tls_key_t ruby_current_ec_key; - RUBY_SYMBOL_EXPORT_END #define GET_VM() rb_current_vm() @@ -1764,7 +1762,15 @@ rb_ec_vm_ptr(const rb_execution_context_t *ec) static inline rb_execution_context_t * rb_current_execution_context(void) { +#ifdef RB_THREAD_LOCAL_SPECIFIER + #if __APPLE__ + rb_execution_context_t *ec = rb_current_ec(); + #else + rb_execution_context_t *ec = ruby_current_ec; + #endif +#else rb_execution_context_t *ec = native_tls_get(ruby_current_ec_key); +#endif VM_ASSERT(ec != NULL); return ec; }