/root/doris/be/src/util/thread.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 | | // This file is copied from |
18 | | // https://github.com/apache/impala/blob/branch-2.9.0/be/src/util/thread.h |
19 | | // and modified by Doris |
20 | | |
21 | | #pragma once |
22 | | #include <butil/macros.h> |
23 | | #include <pthread.h> |
24 | | #include <stdint.h> |
25 | | |
26 | | #include <functional> |
27 | | #include <string> |
28 | | #include <utility> |
29 | | |
30 | | #include "common/status.h" |
31 | | #include "gutil/ref_counted.h" |
32 | | #include "util/countdown_latch.h" |
33 | | |
34 | | namespace doris { |
35 | | class WebPageHandler; |
36 | | |
37 | | class Thread : public RefCountedThreadSafe<Thread> { |
38 | | public: |
39 | | enum CreateFlags { NO_FLAGS = 0, NO_STACK_WATCHDOG = 1 }; |
40 | | |
41 | | template <class F> |
42 | | static Status create_with_flags(const std::string& category, const std::string& name, |
43 | | const F& f, uint64_t flags, scoped_refptr<Thread>* holder) { |
44 | | return start_thread(category, name, f, flags, holder); |
45 | | } |
46 | | |
47 | | template <class F> |
48 | | static Status create(const std::string& category, const std::string& name, const F& f, |
49 | 28 | scoped_refptr<Thread>* holder) { |
50 | 28 | return start_thread(category, name, f, NO_FLAGS, holder); |
51 | 28 | } _ZN5doris6Thread6createIFvvEEENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESB_RKT_P13scoped_refptrIS0_E Line | Count | Source | 49 | 1 | scoped_refptr<Thread>* holder) { | 50 | 1 | return start_thread(category, name, f, NO_FLAGS, holder); | 51 | 1 | } |
task_worker_pool.cpp:_ZN5doris6Thread6createIZNS_19PriorTaskWorkerPoolC1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEiiSt8functionIFvRKNS_17TAgentTaskRequestEEEE3$_0EENS_6StatusESA_SA_RKT_P13scoped_refptrIS0_E Line | Count | Source | 49 | 1 | scoped_refptr<Thread>* holder) { | 50 | 1 | return start_thread(category, name, f, NO_FLAGS, holder); | 51 | 1 | } |
task_worker_pool.cpp:_ZN5doris6Thread6createIZNS_19PriorTaskWorkerPoolC1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEiiSt8functionIFvRKNS_17TAgentTaskRequestEEEE3$_1EENS_6StatusESA_SA_RKT_P13scoped_refptrIS0_E Line | Count | Source | 49 | 1 | scoped_refptr<Thread>* holder) { | 50 | 1 | return start_thread(category, name, f, NO_FLAGS, holder); | 51 | 1 | } |
task_worker_pool.cpp:_ZN5doris6Thread6createIZNS_12ReportWorkerC1ENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEPKNS_11ClusterInfoEiSt8functionIFvvEEE3$_0EENS_6StatusERKS8_SI_RKT_P13scoped_refptrIS0_E Line | Count | Source | 49 | 1 | scoped_refptr<Thread>* holder) { | 50 | 1 | return start_thread(category, name, f, NO_FLAGS, holder); | 51 | 1 | } |
Unexecuted instantiation: olap_server.cpp:_ZN5doris6Thread6createIZNS_13StorageEngine16start_bg_threadsESt10shared_ptrINS_13WorkloadGroupEEE3$_0EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESF_RKT_P13scoped_refptrIS0_E Unexecuted instantiation: olap_server.cpp:_ZN5doris6Thread6createIZNS_13StorageEngine16start_bg_threadsESt10shared_ptrINS_13WorkloadGroupEEE3$_1EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESF_RKT_P13scoped_refptrIS0_E Unexecuted instantiation: olap_server.cpp:_ZN5doris6Thread6createIZNS_13StorageEngine16start_bg_threadsESt10shared_ptrINS_13WorkloadGroupEEE3$_2EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESF_RKT_P13scoped_refptrIS0_E Unexecuted instantiation: olap_server.cpp:_ZN5doris6Thread6createIZNS_13StorageEngine16start_bg_threadsESt10shared_ptrINS_13WorkloadGroupEEE3$_3EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESF_RKT_P13scoped_refptrIS0_E Unexecuted instantiation: olap_server.cpp:_ZN5doris6Thread6createIZNS_13StorageEngine16start_bg_threadsESt10shared_ptrINS_13WorkloadGroupEEE3$_4EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESF_RKT_P13scoped_refptrIS0_E Unexecuted instantiation: olap_server.cpp:_ZN5doris6Thread6createIZNS_13StorageEngine16start_bg_threadsESt10shared_ptrINS_13WorkloadGroupEEE3$_5EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESF_RKT_P13scoped_refptrIS0_E Unexecuted instantiation: olap_server.cpp:_ZN5doris6Thread6createIZNS_13StorageEngine16start_bg_threadsESt10shared_ptrINS_13WorkloadGroupEEE3$_6EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESF_RKT_P13scoped_refptrIS0_E Unexecuted instantiation: olap_server.cpp:_ZN5doris6Thread6createIZNS_13StorageEngine16start_bg_threadsESt10shared_ptrINS_13WorkloadGroupEEE3$_7EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESF_RKT_P13scoped_refptrIS0_E Unexecuted instantiation: olap_server.cpp:_ZN5doris6Thread6createIZNS_13StorageEngine16start_bg_threadsESt10shared_ptrINS_13WorkloadGroupEEE3$_8EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESF_RKT_P13scoped_refptrIS0_E Unexecuted instantiation: olap_server.cpp:_ZN5doris6Thread6createIZNS_13StorageEngine16start_bg_threadsESt10shared_ptrINS_13WorkloadGroupEEE3$_9EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESF_RKT_P13scoped_refptrIS0_E Unexecuted instantiation: olap_server.cpp:_ZN5doris6Thread6createIZNS_13StorageEngine16start_bg_threadsESt10shared_ptrINS_13WorkloadGroupEEE4$_10EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESF_RKT_P13scoped_refptrIS0_E Unexecuted instantiation: olap_server.cpp:_ZN5doris6Thread6createIZNS_13StorageEngine16start_bg_threadsESt10shared_ptrINS_13WorkloadGroupEEE4$_11EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESF_RKT_P13scoped_refptrIS0_E Unexecuted instantiation: olap_server.cpp:_ZN5doris6Thread6createIZNS_13StorageEngine16start_bg_threadsESt10shared_ptrINS_13WorkloadGroupEEE4$_12EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESF_RKT_P13scoped_refptrIS0_E wal_manager.cpp:_ZN5doris6Thread6createIZNS_10WalManager4initEvE3$_0EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESC_RKT_P13scoped_refptrIS0_E Line | Count | Source | 49 | 1 | scoped_refptr<Thread>* holder) { | 50 | 1 | return start_thread(category, name, f, NO_FLAGS, holder); | 51 | 1 | } |
wal_manager.cpp:_ZN5doris6Thread6createIZNS_10WalManager19_init_wal_dirs_infoEvE3$_0EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESC_RKT_P13scoped_refptrIS0_E Line | Count | Source | 49 | 14 | scoped_refptr<Thread>* holder) { | 50 | 14 | return start_thread(category, name, f, NO_FLAGS, holder); | 51 | 14 | } |
Unexecuted instantiation: broker_mgr.cpp:_ZN5doris6Thread6createIZNS_9BrokerMgrC1EPNS_7ExecEnvEE3$_0EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESE_RKT_P13scoped_refptrIS0_E external_scan_context_mgr.cpp:_ZN5doris6Thread6createIZNS_22ExternalScanContextMgrC1EPNS_7ExecEnvEE3$_0EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESE_RKT_P13scoped_refptrIS0_E Line | Count | Source | 49 | 4 | scoped_refptr<Thread>* holder) { | 50 | 4 | return start_thread(category, name, f, NO_FLAGS, holder); | 51 | 4 | } |
fragment_mgr.cpp:_ZN5doris6Thread6createIZNS_11FragmentMgrC1EPNS_7ExecEnvEE3$_0EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESE_RKT_P13scoped_refptrIS0_E Line | Count | Source | 49 | 4 | scoped_refptr<Thread>* holder) { | 50 | 4 | return start_thread(category, name, f, NO_FLAGS, holder); | 51 | 4 | } |
Unexecuted instantiation: load_channel_mgr.cpp:_ZN5doris6Thread6createIZNS_14LoadChannelMgr16_start_bg_workerEvE3$_0EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESC_RKT_P13scoped_refptrIS0_E Unexecuted instantiation: load_path_mgr.cpp:_ZN5doris6Thread6createIZNS_11LoadPathMgr4initEvE3$_0EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESC_RKT_P13scoped_refptrIS0_E Unexecuted instantiation: result_buffer_mgr.cpp:_ZN5doris6Thread6createIZNS_15ResultBufferMgr4initEvE3$_0EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESC_RKT_P13scoped_refptrIS0_E data_consumer_pool.cpp:_ZN5doris6Thread6createIZNS_16DataConsumerPool15start_bg_workerEvE3$_0EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESC_RKT_P13scoped_refptrIS0_E Line | Count | Source | 49 | 1 | scoped_refptr<Thread>* holder) { | 50 | 1 | return start_thread(category, name, f, NO_FLAGS, holder); | 51 | 1 | } |
Unexecuted instantiation: workload_sched_policy_mgr.cpp:_ZN5doris6Thread6createIZNS_22WorkloadSchedPolicyMgr5startEPNS_7ExecEnvEE3$_0EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESE_RKT_P13scoped_refptrIS0_E Unexecuted instantiation: spill_stream_manager.cpp:_ZN5doris6Thread6createIZNS_10vectorized18SpillStreamManager4initEvE3$_0EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESD_RKT_P13scoped_refptrIS0_E Unexecuted instantiation: cloud_storage_engine.cpp:_ZN5doris6Thread6createIZNS_18CloudStorageEngine16start_bg_threadsESt10shared_ptrINS_13WorkloadGroupEEE3$_0EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESF_RKT_P13scoped_refptrIS0_E Unexecuted instantiation: cloud_storage_engine.cpp:_ZN5doris6Thread6createIZNS_18CloudStorageEngine16start_bg_threadsESt10shared_ptrINS_13WorkloadGroupEEE3$_1EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESF_RKT_P13scoped_refptrIS0_E Unexecuted instantiation: cloud_storage_engine.cpp:_ZN5doris6Thread6createIZNS_18CloudStorageEngine16start_bg_threadsESt10shared_ptrINS_13WorkloadGroupEEE3$_2EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESF_RKT_P13scoped_refptrIS0_E Unexecuted instantiation: cloud_storage_engine.cpp:_ZN5doris6Thread6createIZNS_18CloudStorageEngine16start_bg_threadsESt10shared_ptrINS_13WorkloadGroupEEE3$_3EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESF_RKT_P13scoped_refptrIS0_E Unexecuted instantiation: cloud_storage_engine.cpp:_ZN5doris6Thread6createIZNS_18CloudStorageEngine16start_bg_threadsESt10shared_ptrINS_13WorkloadGroupEEE3$_4EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESF_RKT_P13scoped_refptrIS0_E Unexecuted instantiation: cloud_storage_engine.cpp:_ZN5doris6Thread6createIZNS_18CloudStorageEngine16start_bg_threadsESt10shared_ptrINS_13WorkloadGroupEEE3$_5EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESF_RKT_P13scoped_refptrIS0_E Unexecuted instantiation: cloud_storage_engine.cpp:_ZN5doris6Thread6createIZNS_18CloudStorageEngine16start_bg_threadsESt10shared_ptrINS_13WorkloadGroupEEE3$_6EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESF_RKT_P13scoped_refptrIS0_E Unexecuted instantiation: cloud_txn_delete_bitmap_cache.cpp:_ZN5doris6Thread6createIZNS_25CloudTxnDeleteBitmapCache4initEvE3$_0EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESC_RKT_P13scoped_refptrIS0_E |
52 | | |
53 | | template <class F, class A1> |
54 | | static Status create(const std::string& category, const std::string& name, const F& f, |
55 | 2.40k | const A1& a1, scoped_refptr<Thread>* holder) { |
56 | 2.40k | return start_thread(category, name, std::bind(f, a1), NO_FLAGS, holder); |
57 | 2.40k | } _ZN5doris6Thread6createIMNS_14CountDownLatchEFvvEPS2_EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESE_RKT_RKT0_P13scoped_refptrIS0_E Line | Count | Source | 55 | 1 | const A1& a1, scoped_refptr<Thread>* holder) { | 56 | 1 | return start_thread(category, name, std::bind(f, a1), NO_FLAGS, holder); | 57 | 1 | } |
_ZN5doris6Thread6createIFvlEiEENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESB_RKT_RKT0_P13scoped_refptrIS0_E Line | Count | Source | 55 | 1.00k | const A1& a1, scoped_refptr<Thread>* holder) { | 56 | 1.00k | return start_thread(category, name, std::bind(f, a1), NO_FLAGS, holder); | 57 | 1.00k | } |
Unexecuted instantiation: _ZN5doris6Thread6createIMNS_2io15FileHandleCacheEFvvEPS3_EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESF_RKT_RKT0_P13scoped_refptrIS0_E _ZN5doris6Thread6createIMNS_10ThreadPoolEFvvEPS2_EENS_6StatusERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESE_RKT_RKT0_P13scoped_refptrIS0_E Line | Count | Source | 55 | 1.40k | const A1& a1, scoped_refptr<Thread>* holder) { | 56 | 1.40k | return start_thread(category, name, std::bind(f, a1), NO_FLAGS, holder); | 57 | 1.40k | } |
|
58 | | |
59 | | template <class F, class A1, class A2> |
60 | | static Status create(const std::string& category, const std::string& name, const F& f, |
61 | | const A1& a1, const A2& a2, scoped_refptr<Thread>* holder) { |
62 | | return start_thread(category, name, std::bind(f, a1, a2), NO_FLAGS, holder); |
63 | | } |
64 | | |
65 | | template <class F, class A1, class A2, class A3> |
66 | | static Status create(const std::string& category, const std::string& name, const F& f, |
67 | | const A1& a1, const A2& a2, const A3& a3, scoped_refptr<Thread>* holder) { |
68 | | return start_thread(category, name, std::bind(f, a1, a2, a3), NO_FLAGS, holder); |
69 | | } |
70 | | |
71 | | template <class F, class A1, class A2, class A3, class A4> |
72 | | static Status create(const std::string& category, const std::string& name, const F& f, |
73 | | const A1& a1, const A2& a2, const A3& a3, const A4& a4, |
74 | | scoped_refptr<Thread>* holder) { |
75 | | return start_thread(category, name, std::bind(f, a1, a2, a3, a4), NO_FLAGS, holder); |
76 | | } |
77 | | |
78 | | template <class F, class A1, class A2, class A3, class A4, class A5> |
79 | | static Status create(const std::string& category, const std::string& name, const F& f, |
80 | | const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, |
81 | | scoped_refptr<Thread>* holder) { |
82 | | return start_thread(category, name, std::bind(f, a1, a2, a3, a4, a5), NO_FLAGS, holder); |
83 | | } |
84 | | |
85 | | template <class F, class A1, class A2, class A3, class A4, class A5, class A6> |
86 | | static Status create(const std::string& category, const std::string& name, const F& f, |
87 | | const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, |
88 | | const A6& a6, scoped_refptr<Thread>* holder) { |
89 | | return start_thread(category, name, std::bind(f, a1, a2, a3, a4, a5, a6), NO_FLAGS, holder); |
90 | | } |
91 | | |
92 | | static void set_self_name(const std::string& name); |
93 | | |
94 | | #ifndef __APPLE__ |
95 | | static void set_idle_sched(); |
96 | | |
97 | | static void set_thread_nice_value(); |
98 | | #endif |
99 | | |
100 | | ~Thread(); |
101 | | |
102 | | // Blocks until this thread finishes execution. Once this method returns, the thread |
103 | | // will be unregistered with the ThreadMgr and will not appear in the debug UI. |
104 | | void join(); |
105 | | |
106 | | // The thread ID assigned to this thread by the operating system. If the thread |
107 | | // has not yet started running, returns INVALID_TID. |
108 | | // |
109 | | // NOTE: this may block for a short amount of time if the thread has just been |
110 | | // started. |
111 | | int64_t tid() const; |
112 | | |
113 | | // Returns the thread's pthread ID. |
114 | | pthread_t pthread_id() const; |
115 | | |
116 | | const std::string& name() const; |
117 | | const std::string& category() const; |
118 | | std::string to_string() const; |
119 | | |
120 | | // The current thread of execution, or nullptr if the current thread isn't a doris::Thread. |
121 | | // This call is signal-safe. |
122 | | static Thread* current_thread(); |
123 | | |
124 | | // Returns a unique, stable identifier for this thread. Note that this is a static |
125 | | // method and thus can be used on any thread, including the main thread of the |
126 | | // process. |
127 | | // |
128 | | // In general, this should be used when a value is required that is unique to |
129 | | // a thread and must work on any thread including the main process thread. |
130 | | // |
131 | | // NOTE: this is _not_ the TID, but rather a unique value assigned by the |
132 | | // thread implementation. So, this value should not be presented to the user |
133 | | // in log messages, etc. |
134 | | static int64_t unique_thread_id(); |
135 | | |
136 | | // Returns the system thread ID (tid on Linux) for the current thread. Note |
137 | | // that this is a static method and thus can be used from any thread, |
138 | | // including the main thread of the process. This is in contrast to |
139 | | // Thread::tid(), which only works on doris::Threads. |
140 | | // |
141 | | // Thread::tid() will return the same value, but the value is cached in the |
142 | | // Thread object, so will be faster to call. |
143 | | // |
144 | | // Thread::unique_thread_id() (or Thread::tid()) should be preferred for |
145 | | // performance sensitive code, however it is only guaranteed to return a |
146 | | // unique and stable thread ID, not necessarily the system thread ID. |
147 | | static int64_t current_thread_id(); |
148 | | |
149 | | private: |
150 | | friend class ThreadJoiner; |
151 | | |
152 | | enum { |
153 | | INVALID_TID = -1, |
154 | | PARENT_WAITING_TID = -2, |
155 | | }; |
156 | | |
157 | | // User function to be executed by this thread. |
158 | | typedef std::function<void()> ThreadFunctor; |
159 | | Thread(const std::string& category, const std::string& name, ThreadFunctor functor) |
160 | | : _thread(0), |
161 | | _tid(INVALID_TID), |
162 | | _functor(std::move(functor)), |
163 | | _category(std::move(category)), |
164 | | _name(std::move(name)), |
165 | | _done(1), |
166 | 2.43k | _joinable(false) {} |
167 | | |
168 | | // Library-specific thread ID. |
169 | | pthread_t _thread; |
170 | | |
171 | | // OS-specific thread ID. Once the constructor finishes start_thread(), |
172 | | // guaranteed to be set either to a non-negative integer, or to INVALID_TID. |
173 | | // |
174 | | // The tid_ member goes through the following states: |
175 | | // 1. INVALID_TID: the thread has not been started, or has already exited. |
176 | | // 2. PARENT_WAITING_TID: the parent has started the thread, but the |
177 | | // thread has not yet begun running. Therefore the TID is not yet known |
178 | | // but it will be set once the thread starts. |
179 | | // 3. <positive value>: the thread is running. |
180 | | int64_t _tid; |
181 | | |
182 | | const ThreadFunctor _functor; |
183 | | |
184 | | const std::string _category; |
185 | | const std::string _name; |
186 | | |
187 | | // Joiners wait on this latch to be notified if the thread is done. |
188 | | // |
189 | | // Note that Joiners must additionally pthread_join(), otherwise certain |
190 | | // resources that callers expect to be destroyed (like TLS) may still be |
191 | | // alive when a Joiner finishes. |
192 | | CountDownLatch _done; |
193 | | |
194 | | bool _joinable; |
195 | | |
196 | | // Thread local pointer to the current thread of execution. Will be nullptr if the current |
197 | | // thread is not a Thread. |
198 | | static __thread Thread* _tls; |
199 | | |
200 | | // Wait for the running thread to publish its tid. |
201 | | int64_t wait_for_tid() const; |
202 | | |
203 | | // Starts the thread running supervise_thread(), and returns once that thread has |
204 | | // initialised and its TID has been read. Waits for notification from the started |
205 | | // thread that initialisation is complete before returning. On success, stores a |
206 | | // reference to the thread in holder. |
207 | | static Status start_thread(const std::string& category, const std::string& name, |
208 | | const ThreadFunctor& functor, uint64_t flags, |
209 | | scoped_refptr<Thread>* holder); |
210 | | |
211 | | // Wrapper for the user-supplied function. Invoked from the new thread, |
212 | | // with the Thread as its only argument. Executes _functor, but before |
213 | | // doing so registers with the global ThreadMgr and reads the thread's |
214 | | // system ID. After _functor terminates, unregisters with the ThreadMgr. |
215 | | // Always returns nullptr. |
216 | | // |
217 | | // supervise_thread() notifies start_thread() when thread initialisation is |
218 | | // completed via the _tid, which is set to the new thread's system ID. |
219 | | // By that point in time supervise_thread() has also taken a reference to |
220 | | // the Thread object, allowing it to safely refer to it even after the |
221 | | // caller drops its reference. |
222 | | // |
223 | | // Additionally, start_thread() notifies supervise_thread() when the actual |
224 | | // Thread object has been assigned (supervise_thread() is spinning during |
225 | | // this time). Without this, the new thread may reference the actual |
226 | | // Thread object before it has been assigned by start_thread(). See |
227 | | // KUDU-11 for more details. |
228 | | static void* supervise_thread(void* arg); |
229 | | |
230 | | // Invoked when the user-supplied function finishes or in the case of an |
231 | | // abrupt exit (i.e. pthread_exit()). Cleans up after supervise_thread(). |
232 | | static void finish_thread(void* arg); |
233 | | |
234 | | static void init_threadmgr(); |
235 | | }; |
236 | | |
237 | | // Utility to join on a thread, printing warning messages if it |
238 | | // takes too long. For example: |
239 | | // |
240 | | // ThreadJoiner(&my_thread, "processing thread") |
241 | | // .warn_after_ms(1000) |
242 | | // .warn_every_ms(5000) |
243 | | // .Join(); |
244 | | // |
245 | | // TODO: would be nice to offer a way to use ptrace() or signals to |
246 | | // dump the stack trace of the thread we're trying to join on if it |
247 | | // gets stuck. But, after looking for 20 minutes or so, it seems |
248 | | // pretty complicated to get right. |
249 | | class ThreadJoiner { |
250 | | public: |
251 | | explicit ThreadJoiner(Thread* thread); |
252 | | |
253 | | // Start emitting warnings after this many milliseconds. |
254 | | // |
255 | | // Default: 1000 ms. |
256 | | ThreadJoiner& warn_after_ms(int ms); |
257 | | |
258 | | // After the warnings after started, emit another warning at the |
259 | | // given interval. |
260 | | // |
261 | | // Default: 1000 ms. |
262 | | ThreadJoiner& warn_every_ms(int ms); |
263 | | |
264 | | // If the thread has not stopped after this number of milliseconds, give up |
265 | | // joining on it and return Status::Aborted. |
266 | | // |
267 | | // -1 (the default) means to wait forever trying to join. |
268 | | ThreadJoiner& give_up_after_ms(int ms); |
269 | | |
270 | | // Join the thread, subject to the above parameters. If the thread joining |
271 | | // fails for any reason, returns RuntimeError. If it times out, returns |
272 | | // Aborted. |
273 | | Status join(); |
274 | | |
275 | | private: |
276 | | enum { |
277 | | kDefaultWarnAfterMs = 1000, |
278 | | kDefaultWarnEveryMs = 1000, |
279 | | kDefaultGiveUpAfterMs = -1 // forever |
280 | | }; |
281 | | |
282 | | Thread* _thread = nullptr; |
283 | | |
284 | | int _warn_after_ms; |
285 | | int _warn_every_ms; |
286 | | int _give_up_after_ms; |
287 | | |
288 | | DISALLOW_COPY_AND_ASSIGN(ThreadJoiner); |
289 | | }; |
290 | | |
291 | | // Registers /threadz with the debug webserver. |
292 | | void register_thread_display_page(WebPageHandler* web_page_handler); |
293 | | |
294 | | } //namespace doris |