This is an automated email from the ASF dual-hosted git repository.

wwbmmm pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brpc.git


The following commit(s) were added to refs/heads/master by this push:
     new 37c31fb9 fix compiler optimize thread local variable access (#2156)
37c31fb9 is described below

commit 37c31fb9ce0db53ce55beb273c4142aa97c98737
Author: DongSheng He <[email protected]>
AuthorDate: Wed Apr 26 15:45:10 2023 +0800

    fix compiler optimize thread local variable access (#2156)
    
    * fix compiler optimize thread local variable access
    
    * change __thread to BAIDU_THREAD_LOCAL
    
    * Add NOT_ALLOW_OPTIMIZE_THREAD_LOCAL_ACCESS according to compiler and arch
    
    * move thread local access optimization condition to thread_local.h
---
 src/bthread/task_group.cpp | 19 +++++++------------
 src/butil/thread_local.h   | 29 +++++++++++++++++++++++++++++
 2 files changed, 36 insertions(+), 12 deletions(-)

diff --git a/src/bthread/task_group.cpp b/src/bthread/task_group.cpp
index 6f5a4abd..469e1b0b 100644
--- a/src/bthread/task_group.cpp
+++ b/src/bthread/task_group.cpp
@@ -57,7 +57,7 @@ const bool ALLOW_UNUSED dummy_show_per_worker_usage_in_vars =
     ::GFLAGS_NS::RegisterFlagValidator(&FLAGS_show_per_worker_usage_in_vars,
                                     pass_bool);
 
-__thread TaskGroup* tls_task_group = NULL;
+BAIDU_VOLATILE_THREAD_LOCAL(TaskGroup*, tls_task_group, NULL);
 // Sync with TaskMeta::local_storage when a bthread is created or destroyed.
 // During running, the two fields may be inconsistent, use tls_bls as the
 // groundtruth.
@@ -68,7 +68,7 @@ extern void return_keytable(bthread_keytable_pool_t*, 
KeyTable*);
 
 // [Hacky] This is a special TLS set by bthread-rpc privately... to save
 // overhead of creation keytable, may be removed later.
-BAIDU_THREAD_LOCAL void* tls_unique_user_ptr = NULL;
+BAIDU_VOLATILE_THREAD_LOCAL(void*, tls_unique_user_ptr, NULL);
 
 const TaskStatistics EMPTY_STAT = { 0, 0 };
 
@@ -248,9 +248,6 @@ int TaskGroup::init(size_t runqueue_capacity) {
     return 0;
 }
 
-#if defined(__linux__) && defined(__aarch64__) && defined(__clang__)
-    __attribute__((optnone))
-#endif
 void TaskGroup::task_runner(intptr_t skip_remained) {
     // NOTE: tls_task_group is volatile since tasks are moved around
     //       different groups.
@@ -301,7 +298,7 @@ void TaskGroup::task_runner(intptr_t skip_remained) {
         }
 
         // Group is probably changed
-        g = tls_task_group;
+        g =  BAIDU_GET_VOLATILE_THREAD_LOCAL(tls_task_group);
 
         // TODO: Save thread_return
         (void)thread_return;
@@ -570,9 +567,6 @@ void TaskGroup::sched(TaskGroup** pg) {
     sched_to(pg, next_tid);
 }
 
-#if defined(__linux__) && defined(__aarch64__) && defined(__clang__)
-    __attribute__((optnone))
-#endif
 void TaskGroup::sched_to(TaskGroup** pg, TaskMeta* next_meta) {
     TaskGroup* g = *pg;
 #ifndef NDEBUG
@@ -614,7 +608,7 @@ void TaskGroup::sched_to(TaskGroup** pg, TaskMeta* 
next_meta) {
             if (next_meta->stack != cur_meta->stack) {
                 jump_stack(cur_meta->stack, next_meta->stack);
                 // probably went to another group, need to assign g again.
-                g = tls_task_group;
+                g = BAIDU_GET_VOLATILE_THREAD_LOCAL(tls_task_group);
             }
 #ifndef NDEBUG
             else {
@@ -633,12 +627,13 @@ void TaskGroup::sched_to(TaskGroup** pg, TaskMeta* 
next_meta) {
         RemainedFn fn = g->_last_context_remained;
         g->_last_context_remained = NULL;
         fn(g->_last_context_remained_arg);
-        g = tls_task_group;
+        g = BAIDU_GET_VOLATILE_THREAD_LOCAL(tls_task_group);
     }
 
     // Restore errno
     errno = saved_errno;
-    tls_unique_user_ptr = saved_unique_user_ptr;
+    // tls_unique_user_ptr probably changed.
+    BAIDU_SET_VOLATILE_THREAD_LOCAL(tls_unique_user_ptr, 
saved_unique_user_ptr);
 
 #ifndef NDEBUG
     --g->_sched_recursive_guard;
diff --git a/src/butil/thread_local.h b/src/butil/thread_local.h
index 1c462b0f..4f77e958 100644
--- a/src/butil/thread_local.h
+++ b/src/butil/thread_local.h
@@ -30,6 +30,35 @@
 #define BAIDU_THREAD_LOCAL __thread
 #endif  // _MSC_VER
 
+#define BAIDU_VOLATILE_THREAD_LOCAL(type, var_name, default_value)             
\
+  BAIDU_THREAD_LOCAL type var_name = default_value;                            
          \
+  static __attribute__((noinline, unused)) type get_##var_name(void) {         
\
+    asm volatile("");                                                          
\
+    return var_name;                                                           
\
+  }                                                                            
\
+  static __attribute__((noinline, unused)) type *get_ptr_##var_name(void) {    
\
+    type *ptr = &var_name;                                                     
\
+    asm volatile("" : "+rm"(ptr));                                             
\
+    return ptr;                                                                
\
+  }                                                                            
\
+  static __attribute__((noinline, unused)) void set_##var_name(type v) {       
\
+    asm volatile("");                                                          
\
+    var_name = v;                                                              
\
+  }
+
+#if defined(__clang__) && (defined(__aarch64__) || defined(__arm64__))
+// Clang compiler is incorrectly caching the address of thread_local variables
+// across a suspend-point. The following macros used to disable the volatile
+// thread local access optimization.
+#define BAIDU_GET_VOLATILE_THREAD_LOCAL(var_name) get_##var_name()
+#define BAIDU_GET_PTR_VOLATILE_THREAD_LOCAL(var_name) get_ptr_##var_name()
+#define BAIDU_SET_VOLATILE_THREAD_LOCAL(var_name, value) set_##var_name(value)
+#else
+#define BAIDU_GET_VOLATILE_THREAD_LOCAL(var_name) var_name
+#define BAIDU_GET_PTR_VOLATILE_THREAD_LOCAL(var_name) &##var_name
+#define BAIDU_SET_VOLATILE_THREAD_LOCAL(var_name, value) var_name = value
+#endif
+
 namespace butil {
 
 // Get a thread-local object typed T. The object will be default-constructed


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to