Skip to content

bthread: use macros for safer thread-local access on ARM#3380

Open
altman08 wants to merge 1 commit into
apache:masterfrom
altman08:master
Open

bthread: use macros for safer thread-local access on ARM#3380
altman08 wants to merge 1 commit into
apache:masterfrom
altman08:master

Conversation

@altman08

Copy link
Copy Markdown
Contributor

Route accesses to tls_task_group, tls_task_group_nosignal, tls_bls and several mutex-profiling thread-locals (tls_inside_lock, tls_warn_up, tls_pthread_lock_count, tls_csites, tls_ever_created_keytable) through the BAIDU_(GET|SET|GET_PTR)_VOLATILE_THREAD_LOCAL macros instead of touching the raw __thread variables directly.

On aarch64/clang the compiler can incorrectly cache the address of a thread_local variable across a suspend point (e.g. when a bthread is rescheduled onto another worker), so raw accesses can silently read a stale TaskGroup*/LocalStorage. Going through the accessor macros everywhere forces a fresh, non-cached load/store on those platforms while staying a plain variable access elsewhere.

Add bthread::tls_bls_ptr() as the single helper for obtaining the current LocalStorage*, and update all call sites (bthread.cpp, butex.cpp, fd.cpp, key.cpp, mutex.cpp, task_control.cpp, brpc/controller.cpp, test/bthread_unittest.cpp) to use it instead of declaring their own stale/mistyped extern references to tls_task_group or tls_bls.

Also hardens borrow_keytable()/return_keytable() in key.cpp: the KeyTableList pointer obtained under the read lock is no longer reused after re-acquiring the write lock, since pool->list/pool->destroyed may change concurrently via bthread_keytable_pool_destroy(); the thread-local list is drained first before falling back to the pool's global free list.

What problem does this PR solve?

Issue Number: resolve

Problem Summary:

What is changed and the side effects?

Changed:

Side effects:

  • Performance effects:

  • Breaking backward compatibility:


Check List:

Route accesses to tls_task_group, tls_task_group_nosignal, tls_bls and
several mutex-profiling thread-locals (tls_inside_lock, tls_warn_up,
tls_pthread_lock_count, tls_csites, tls_ever_created_keytable) through
the BAIDU_(GET|SET|GET_PTR)_VOLATILE_THREAD_LOCAL macros instead of
touching the raw __thread variables directly.

On aarch64/clang the compiler can incorrectly cache the address of a
thread_local variable across a suspend point (e.g. when a bthread is
rescheduled onto another worker), so raw accesses can silently read a
stale TaskGroup*/LocalStorage. Going through the accessor macros
everywhere forces a fresh, non-cached load/store on those platforms
while staying a plain variable access elsewhere.

Add bthread::tls_bls_ptr() as the single helper for obtaining the
current LocalStorage*, and update all call sites (bthread.cpp,
butex.cpp, fd.cpp, key.cpp, mutex.cpp, task_control.cpp,
brpc/controller.cpp, test/bthread_unittest.cpp) to use it instead of
declaring their own stale/mistyped extern references to tls_task_group
or tls_bls.

Also hardens borrow_keytable()/return_keytable() in key.cpp: the
KeyTableList pointer obtained under the read lock is no longer reused
after re-acquiring the write lock, since pool->list/pool->destroyed
may change concurrently via bthread_keytable_pool_destroy(); the
thread-local list is drained first before falling back to the pool's
global free list.
Comment thread src/bthread/bthread.cpp
TaskGroup* g = tls_task_group_nosignal;
if (NULL == g) {
auto g = BAIDU_GET_VOLATILE_THREAD_LOCAL(tls_task_group_nosignal);
if (NULL == g || g->tag() != tag) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use CHECK_EQ(g->tag(), tag) is more appropriate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants