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   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 quicClientSessionAllocator;
126   ProxyAllocator quicHandshakeAllocator;
127   ProxyAllocator quicBidiStreamAllocator;
128   ProxyAllocator quicSendStreamAllocator;
129   ProxyAllocator quicReceiveStreamAllocator;
130   ProxyAllocator quicStreamManagerAllocator;
131   ProxyAllocator httpServerSessionAllocator;
132   ProxyAllocator hdrHeapAllocator;
133   ProxyAllocator strHeapAllocator;
134   ProxyAllocator cacheVConnectionAllocator;
135   ProxyAllocator openDirEntryAllocator;
136   ProxyAllocator ramCacheCLFUSEntryAllocator;
137   ProxyAllocator ramCacheLRUEntryAllocator;
138   ProxyAllocator evacuationBlockAllocator;
139   ProxyAllocator ioDataAllocator;
140   ProxyAllocator ioAllocator;
141   ProxyAllocator ioBlockAllocator;
142 
143   /** Start the underlying thread.
144 
145       The thread name is set to @a name. The stack for the thread is either @a stack or, if that is
146       @c nullptr a stack of size @a stacksize is allocated and used. If @a f is present and valid it
147       is called in the thread context. Otherwise the method @c execute is invoked.
148   */
149   void start(const char *name, void *stack, size_t stacksize, ThreadFunction const &f = ThreadFunction());
150 
151   virtual void execute() = 0;
152 
153   /** Get the current ATS high resolution time.
154       This gets a cached copy of the time so it is very fast and reasonably accurate.
155       The cached time is updated every time the actual operating system time is fetched which is
156       at least every 10ms and generally more frequently.
157       @note The cached copy shared among threads which means the cached copy is updated
158       for all threads if any thread updates it.
159   */
160   static ink_hrtime get_hrtime();
161 
162   /** Get the operating system high resolution time.
163 
164       Get the current time at high resolution from the operating system.  This is more expensive
165       than @c get_hrtime and should be used only where very precise timing is required.
166 
167       @note This also updates the cached time.
168   */
169   static ink_hrtime get_hrtime_updated();
170 
171   Thread(const Thread &) = delete;
172   Thread &operator=(const Thread &) = delete;
173   virtual ~Thread();
174 
175 protected:
176   Thread();
177 
178   static ink_hrtime cur_time;
179 };
180 
181 extern Thread *this_thread();
182 
183 TS_INLINE ink_hrtime
184 Thread::get_hrtime()
185 {
186   return cur_time;
187 }
188 
189 TS_INLINE ink_hrtime
190 Thread::get_hrtime_updated()
191 {
192   return cur_time = ink_get_hrtime_internal();
193 }
194