summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKoichi Sasada <ko1@atdot.net>2020-10-19 16:47:32 +0900
committerKoichi Sasada <ko1@atdot.net>2020-10-20 01:05:06 +0900
commit319afed20fba8f9b44611d16e4930260f7b56b86 (patch)
tree39d24da0464a39a2bfbc93f4ab5849945bc6f652
parent3f97940252a37db6e601b4bb1aa1e87204f769df (diff)
Use language TLS specifier if it is possible.
To access TLS, it is faster to use language TLS specifier instead of using pthread_get/setspecific functions. Original proposal is: Use native thread locals. #3665
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/3667
-rw-r--r--ractor.h8
-rw-r--r--thread_pthread.c16
-rw-r--r--thread_pthread.h23
-rw-r--r--thread_win32.h4
-rw-r--r--vm.c19
-rw-r--r--vm_core.h10
6 files changed, 78 insertions, 2 deletions
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;
}