/src/brpc/src/butil/thread_local.h
Line | Count | Source |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | |
18 | | // Date: Mon. Nov 7 14:47:36 CST 2011 |
19 | | |
20 | | #ifndef BUTIL_THREAD_LOCAL_H |
21 | | #define BUTIL_THREAD_LOCAL_H |
22 | | |
23 | | #include <new> // std::nothrow |
24 | | #include <cstddef> // NULL |
25 | | #include "butil/macros.h" |
26 | | |
27 | | #ifdef _MSC_VER |
28 | | #define BAIDU_THREAD_LOCAL __declspec(thread) |
29 | | #else |
30 | | #define BAIDU_THREAD_LOCAL __thread |
31 | | #endif // _MSC_VER |
32 | | |
33 | | #define BAIDU_VOLATILE_THREAD_LOCAL(type, var_name, default_value) \ |
34 | | BAIDU_THREAD_LOCAL type var_name = default_value; \ |
35 | 2 | __attribute__((noinline, unused)) type get_##var_name(void) { \ |
36 | 2 | asm volatile(""); \ |
37 | 2 | return var_name; \ |
38 | 2 | } \ bthread::get_tls_task_group() Line | Count | Source | 35 | 2 | __attribute__((noinline, unused)) type get_##var_name(void) { \ | 36 | 2 | asm volatile(""); \ | 37 | 2 | return var_name; \ | 38 | 2 | } \ |
Unexecuted instantiation: bthread::get_tls_bls() Unexecuted instantiation: bthread::get_tls_unique_user_ptr() |
39 | 0 | __attribute__((noinline, unused)) type *get_ptr_##var_name(void) { \ |
40 | 0 | type *ptr = &var_name; \ |
41 | 0 | asm volatile("" : "+rm"(ptr)); \ |
42 | 0 | return ptr; \ |
43 | 0 | } \ Unexecuted instantiation: bthread::get_ptr_tls_task_group() Unexecuted instantiation: bthread::get_ptr_tls_bls() Unexecuted instantiation: bthread::get_ptr_tls_unique_user_ptr() |
44 | 0 | __attribute__((noinline, unused)) void set_##var_name(type v) { \ |
45 | 0 | asm volatile(""); \ |
46 | 0 | var_name = v; \ |
47 | 0 | } Unexecuted instantiation: bthread::set_tls_task_group(bthread::TaskGroup*) Unexecuted instantiation: bthread::set_tls_bls(bthread::LocalStorage) Unexecuted instantiation: bthread::set_tls_unique_user_ptr(void*) |
48 | | |
49 | | #define STATIC_MEMBER_BAIDU_VOLATILE_THREAD_LOCAL(type, var_name) \ |
50 | | static BAIDU_THREAD_LOCAL type var_name; \ |
51 | 0 | static __attribute__((noinline, unused)) type get_##var_name(void) { \ |
52 | 0 | asm volatile(""); \ |
53 | 0 | return var_name; \ |
54 | 0 | } \ Unexecuted instantiation: butil::ObjectPool<butil::IOBufSample>::get__local_pool() Unexecuted instantiation: butil::ObjectPool<bthread::SampledContention>::get__local_pool() Unexecuted instantiation: butil::ObjectPool<bthread::StackFactory<bthread::SmallStackClass>::Wrapper>::get__local_pool() Unexecuted instantiation: butil::ObjectPool<bthread::StackFactory<bthread::NormalStackClass>::Wrapper>::get__local_pool() Unexecuted instantiation: butil::ObjectPool<bthread::StackFactory<bthread::LargeStackClass>::Wrapper>::get__local_pool() Unexecuted instantiation: butil::ResourcePool<bthread::TaskMeta>::get__local_pool() Unexecuted instantiation: butil::ResourcePool<bthread::TimerThread::Task>::get__local_pool() Unexecuted instantiation: butil::ObjectPool<logging::LogRequest>::get__local_pool() Unexecuted instantiation: butil::ResourcePool<butil::details::ExtendedEndPoint>::get__local_pool() Unexecuted instantiation: butil::ObjectPool<bthread::Butex>::get__local_pool() |
55 | | static __attribute__((noinline, unused)) type *get_ptr_##var_name(void) { \ |
56 | | type *ptr = &var_name; \ |
57 | | asm volatile("" : "+rm"(ptr)); \ |
58 | | return ptr; \ |
59 | | } \ |
60 | 0 | static __attribute__((noinline, unused)) void set_##var_name(type v) { \ |
61 | 0 | asm volatile(""); \ |
62 | 0 | var_name = v; \ |
63 | 0 | } Unexecuted instantiation: butil::ObjectPool<butil::IOBufSample>::set__local_pool(butil::ObjectPool<butil::IOBufSample>::LocalPool*) Unexecuted instantiation: butil::ObjectPool<bthread::SampledContention>::set__local_pool(butil::ObjectPool<bthread::SampledContention>::LocalPool*) Unexecuted instantiation: butil::ObjectPool<bthread::StackFactory<bthread::SmallStackClass>::Wrapper>::set__local_pool(butil::ObjectPool<bthread::StackFactory<bthread::SmallStackClass>::Wrapper>::LocalPool*) Unexecuted instantiation: butil::ObjectPool<bthread::StackFactory<bthread::NormalStackClass>::Wrapper>::set__local_pool(butil::ObjectPool<bthread::StackFactory<bthread::NormalStackClass>::Wrapper>::LocalPool*) Unexecuted instantiation: butil::ObjectPool<bthread::StackFactory<bthread::LargeStackClass>::Wrapper>::set__local_pool(butil::ObjectPool<bthread::StackFactory<bthread::LargeStackClass>::Wrapper>::LocalPool*) Unexecuted instantiation: butil::ResourcePool<bthread::TaskMeta>::set__local_pool(butil::ResourcePool<bthread::TaskMeta>::LocalPool*) Unexecuted instantiation: butil::ResourcePool<bthread::TimerThread::Task>::set__local_pool(butil::ResourcePool<bthread::TimerThread::Task>::LocalPool*) Unexecuted instantiation: butil::ObjectPool<logging::LogRequest>::set__local_pool(butil::ObjectPool<logging::LogRequest>::LocalPool*) Unexecuted instantiation: butil::ResourcePool<butil::details::ExtendedEndPoint>::set__local_pool(butil::ResourcePool<butil::details::ExtendedEndPoint>::LocalPool*) Unexecuted instantiation: butil::ObjectPool<bthread::Butex>::set__local_pool(butil::ObjectPool<bthread::Butex>::LocalPool*) |
64 | | |
65 | | #if (defined (__aarch64__) && defined (__GNUC__)) || defined(__clang__) |
66 | | // GNU compiler under aarch and Clang compiler is incorrectly caching the |
67 | | // address of thread_local variables across a suspend-point. The following |
68 | | // macros used to disable the volatile thread local access optimization. |
69 | 2 | #define BAIDU_GET_VOLATILE_THREAD_LOCAL(var_name) get_##var_name() |
70 | 0 | #define BAIDU_GET_PTR_VOLATILE_THREAD_LOCAL(var_name) get_ptr_##var_name() |
71 | 0 | #define BAIDU_SET_VOLATILE_THREAD_LOCAL(var_name, value) set_##var_name(value) |
72 | | |
73 | | #define EXTERN_BAIDU_VOLATILE_THREAD_LOCAL(type, var_name) \ |
74 | | extern type get_##var_name(void); \ |
75 | | extern type *get_ptr_##var_name(void); \ |
76 | | extern void set_##var_name(type v) |
77 | | #else |
78 | | #define BAIDU_GET_VOLATILE_THREAD_LOCAL(var_name) var_name |
79 | | #define BAIDU_GET_PTR_VOLATILE_THREAD_LOCAL(var_name) &var_name |
80 | | #define BAIDU_SET_VOLATILE_THREAD_LOCAL(var_name, value) var_name = value |
81 | | #define EXTERN_BAIDU_VOLATILE_THREAD_LOCAL(type, var_name) \ |
82 | | extern BAIDU_THREAD_LOCAL type var_name |
83 | | #endif |
84 | | |
85 | | namespace butil { |
86 | | |
87 | | // Get a thread-local object typed T. The object will be default-constructed |
88 | | // at the first call to this function, and will be deleted when thread |
89 | | // exits. |
90 | | template <typename T> inline T* get_thread_local(); |
91 | | |
92 | | // |fn| or |fn(arg)| will be called at caller's exit. If caller is not a |
93 | | // thread, fn will be called at program termination. Calling sequence is LIFO: |
94 | | // last registered function will be called first. Duplication of functions |
95 | | // are not checked. This function is often used for releasing thread-local |
96 | | // resources declared with __thread which is much faster than |
97 | | // pthread_getspecific or boost::thread_specific_ptr. |
98 | | // Returns 0 on success, -1 otherwise and errno is set. |
99 | | int thread_atexit(void (*fn)()); |
100 | | int thread_atexit(void (*fn)(void*), void* arg); |
101 | | |
102 | | // Remove registered function, matched functions will not be called. |
103 | | void thread_atexit_cancel(void (*fn)()); |
104 | | void thread_atexit_cancel(void (*fn)(void*), void* arg); |
105 | | |
106 | | // Delete the typed-T object whose address is `arg'. This is a common function |
107 | | // to thread_atexit. |
108 | | template <typename T> void delete_object(void* arg) { |
109 | | delete static_cast<T*>(arg); |
110 | | } |
111 | | |
112 | | } // namespace butil |
113 | | |
114 | | #include "thread_local_inl.h" |
115 | | |
116 | | #endif // BUTIL_THREAD_LOCAL_H |