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
This commit is contained in:
Koichi Sasada 2020-10-19 16:47:32 +09:00
Родитель 3f97940252
Коммит 319afed20f
6 изменённых файлов: 78 добавлений и 2 удалений

Просмотреть файл

@ -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",

Просмотреть файл

@ -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);

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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 */

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

Просмотреть файл

@ -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;
}