1 /** @file
2
3 Thread
4
5 @section license License
6
7 Licensed to the Apache Software Foundation (ASF) under one
8 or more contributor license agreements. See the NOTICE file
9 distributed with this work for additional information
10 regarding copyright ownership. The ASF licenses this file
11 to you under the Apache License, Version 2.0 (the
12 "License"); you may not use this file except in compliance
13 with the License. You may obtain a copy of the License at
14
15 http://www.apache.org/licenses/LICENSE-2.0
16
17 Unless required by applicable law or agreed to in writing, software
18 distributed under the License is distributed on an "AS IS" BASIS,
19 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 See the License for the specific language governing permissions and
21 limitations under the License.
22
23 @section details Details
24
25 Thread class provides the basic functionality for threads. Typically,
26 there will be additional derived classes. Having a common base class
27 for all threads is useful in many cases. I discuss below the use of
28 Threads in the context of Event Subsystem. Hopefully this would be
29 typical of other situations.
30
31 EventProcessor needs to create a bunch of threads. It declares a
32 class called EThread, derived from Thread. It is the responsibility of
33 the EventProcessor to create and manage all the threads needed in the
34 Event Subsystem (Note: we have removed the original ThreadManager class
35 which used to create and manage *all* the threads in the system). By
36 monitoring, we mean checking the heartbeat of each thread and the
37 number of threads in the system etc.
38
39 A derived class should either provide the function (and arguments)
40 needed by the Thread class (see start()), or should define the virtual
41 function execute().
42
43 The Thread class maintains a thread_key which registers *all*
44 the threads in the system (that have been created using Thread or
45 a derived class), using thread specific data calls. Whenever, you
46 call this_thread() you get a pointer to the Thread that is currently
47 executing you. Additionally, the EThread class (derived from Thread)
48 maintains its own independent key. All (and only) the threads created
49 in the Event Subsystem are registered with this key. Thus, whenever you
50 call this_ethread() you get a pointer to EThread. If you happen to call
51 this_ethread() from inside a thread which is not an EThread, you will
52 get a nullptr value (since that thread will not be registered with the
53 EThread key). This will hopefully make the use of this_ethread() safer.
54 Note that an event created with EThread can also call this_thread(),
55 in which case, it will get a pointer to Thread (rather than to EThread).
56
57 */
58
59 #pragma once
60
61 #if !defined(_I_EventSystem_h) && !defined(_P_EventSystem_h)
62 #error "include I_EventSystem.h or P_EventSystem.h"
63 #endif
64
65 #include <functional>
66
67 #include "tscore/ink_platform.h"
68 #include "tscore/ink_thread.h"
69 #include "I_ProxyAllocator.h"
70
71 class ProxyMutex;
72
73 constexpr int MAX_THREAD_NAME_LENGTH = 16;
74
75 /// The signature of a function to be called by a thread.
76 using ThreadFunction = std::function<void()>;
77
78 /**
79 Base class for the threads in the Event System. Thread is the base
80 class for all the thread classes in the Event System. Objects of the
81 Thread class represent spawned or running threads and provide minimal
82 information for its derived classes. Thread objects have a reference
83 to a ProxyMutex, that is used for atomic operations internally, and
84 an ink_thread member that is used to identify the thread in the system.
85
86 You should not create an object of the Thread class, they are typically
87 instantiated after some thread startup mechanism exposed by a processor,
88 but even then you would probably deal with processor functions and
89 not the Thread object itself.
90
91 */
92 class Thread
93 {
94 public:
95 /**
96 System-wide thread identifier. The thread identifier is represented
97 by the platform independent type ink_thread and it is the system-wide
98 value assigned to each thread. It is exposed as a convenience for
99 processors and you should not modify it directly.
100
101 */
102 // NOLINTNEXTLINE(modernize-use-nullptr)
103 ink_thread tid = 0;
104
105 /**
106 Thread lock to ensure atomic operations. The thread lock available
107 to derived classes to ensure atomic operations and protect critical
108 regions. Do not modify this member directly.
109
110 */
111 Ptr<ProxyMutex> mutex;
112
113 virtual void set_specific();
114
115 inkcoreapi static ink_thread_key thread_data_key;
116
117 // For THREAD_ALLOC
118 ProxyAllocator eventAllocator;
119 ProxyAllocator netVCAllocator;
120 ProxyAllocator sslNetVCAllocator;
121 ProxyAllocator quicNetVCAllocator;
122 ProxyAllocator http1ClientSessionAllocator;
123 ProxyAllocator http2ClientSessionAllocator;
124 ProxyAllocator http2StreamAllocator;
125 ProxyAllocator httpSMAllocator;
126 ProxyAllocator quicClientSessionAllocator;
127 ProxyAllocator quicBidiStreamAllocator;
128 ProxyAllocator quicSendStreamAllocator;
129 ProxyAllocator quicReceiveStreamAllocator;
130 ProxyAllocator httpServerSessionAllocator;
131 ProxyAllocator hdrHeapAllocator;
132 ProxyAllocator strHeapAllocator;
133 ProxyAllocator cacheVConnectionAllocator;
134 ProxyAllocator openDirEntryAllocator;
135 ProxyAllocator ramCacheCLFUSEntryAllocator;
136 ProxyAllocator ramCacheLRUEntryAllocator;
137 ProxyAllocator evacuationBlockAllocator;
138 ProxyAllocator ioDataAllocator;
139 ProxyAllocator ioAllocator;
140 ProxyAllocator ioBlockAllocator;
141 // From InkAPI (plugins wrappers)
142 ProxyAllocator apiHookAllocator;
143 ProxyAllocator INKContAllocator;
144 ProxyAllocator INKVConnAllocator;
145 ProxyAllocator mHandleAllocator;
146
147 /** Start the underlying thread.
148
149 The thread name is set to @a name. The stack for the thread is either @a stack or, if that is
150 @c nullptr a stack of size @a stacksize is allocated and used. If @a f is present and valid it
151 is called in the thread context. Otherwise the method @c execute is invoked.
152 */
153 void start(const char *name, void *stack, size_t stacksize, ThreadFunction const &f = ThreadFunction());
154
155 virtual void execute() = 0;
156
157 /** Get the current ATS high resolution time.
158 This gets a cached copy of the time so it is very fast and reasonably accurate.
159 The cached time is updated every time the actual operating system time is fetched which is
160 at least every 10ms and generally more frequently.
161 @note The cached copy shared among threads which means the cached copy is updated
162 for all threads if any thread updates it.
163 */
164 static ink_hrtime get_hrtime();
165
166 /** Get the operating system high resolution time.
167
168 Get the current time at high resolution from the operating system. This is more expensive
169 than @c get_hrtime and should be used only where very precise timing is required.
170
171 @note This also updates the cached time.
172 */
173 static ink_hrtime get_hrtime_updated();
174
175 Thread(const Thread &) = delete;
176 Thread &operator=(const Thread &) = delete;
177 virtual ~Thread();
178
179 protected:
180 Thread();
181
182 static ink_hrtime cur_time;
183 };
184
185 extern Thread *this_thread();
186
187 TS_INLINE ink_hrtime
get_hrtime()188 Thread::get_hrtime()
189 {
190 return cur_time;
191 }
192
193 TS_INLINE ink_hrtime
get_hrtime_updated()194 Thread::get_hrtime_updated()
195 {
196 return cur_time = ink_get_hrtime_internal();
197 }
198