1//
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions
4// are met:
5// * Redistributions of source code must retain the above copyright
6// notice, this list of conditions and the following disclaimer.
7// * Redistributions in binary form must reproduce the above copyright
8// notice, this list of conditions and the following disclaimer in the
9// documentation and/or other materials provided with the distribution.
10// * Neither the name of NVIDIA CORPORATION nor the names of its
11// contributors may be used to endorse or promote products derived
12// from this software without specific prior written permission.
13//
14// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
15// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25//
26// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
27// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
28// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
29
30#ifndef PSFOUNDATION_PSTHREAD_H
31#define PSFOUNDATION_PSTHREAD_H
32
33#include "PsUserAllocated.h"
34
35// dsequeira: according to existing comment here (David Black would be my guess)
36// "This is useful to reduce bus contention on tight spin locks. And it needs
37// to be a macro as the xenon compiler often ignores even __forceinline." What's not
38// clear is why a pause function needs inlining...? (TODO: check with XBox team)
39
40// todo: these need to go somewhere else
41
42#if PX_WINDOWS_FAMILY || PX_XBOXONE || PX_XBOX_SERIES_X
43#define PxSpinLockPause() __asm pause
44#elif PX_LINUX || PX_ANDROID || PX_PS4 || PX_APPLE_FAMILY || PX_SWITCH
45#define PxSpinLockPause() asm("nop")
46#else
47#error "Platform not supported!"
48#endif
49
50namespace physx
51{
52namespace shdfnd
53{
54struct ThreadPriority // todo: put in some other header file
55{
56 enum Enum
57 {
58 /**
59 \brief High priority
60 */
61 eHIGH = 0,
62
63 /**
64 \brief Above Normal priority
65 */
66 eABOVE_NORMAL = 1,
67
68 /**
69 \brief Normal/default priority
70 */
71 eNORMAL = 2,
72
73 /**
74 \brief Below Normal priority
75 */
76 eBELOW_NORMAL = 3,
77
78 /**
79 \brief Low priority.
80 */
81 eLOW = 4,
82 eFORCE_DWORD = 0xffFFffFF
83 };
84};
85
86class Runnable
87{
88 public:
89 Runnable()
90 {
91 }
92 virtual ~Runnable()
93 {
94 }
95 virtual void execute(void)
96 {
97 }
98};
99
100class PX_FOUNDATION_API ThreadImpl
101{
102 public:
103 typedef size_t Id; // space for a pointer or an integer
104 typedef void* (*ExecuteFn)(void*);
105
106 static uint32_t getDefaultStackSize();
107 static Id getId();
108
109 /**
110 Construct (but do not start) the thread object. The OS thread object will not be created
111 until start() is called. Executes in the context
112 of the spawning thread.
113 */
114
115 ThreadImpl();
116
117 /**
118 Construct and start the the thread, passing the given arg to the given fn. (pthread style)
119 */
120
121 ThreadImpl(ExecuteFn fn, void* arg, const char* name);
122
123 /**
124 Deallocate all resources associated with the thread. Should be called in the
125 context of the spawning thread.
126 */
127
128 ~ThreadImpl();
129
130 /**
131 Create the OS thread and start it running. Called in the context of the spawning thread.
132 If an affinity mask has previously been set then it will be applied after the
133 thread has been created.
134 */
135
136 void start(uint32_t stackSize, Runnable* r);
137
138 /**
139 Violently kill the current thread. Blunt instrument, not recommended since
140 it can leave all kinds of things unreleased (stack, memory, mutexes...) Should
141 be called in the context of the spawning thread.
142 */
143
144 void kill();
145
146 /**
147 Stop the thread. Signals the spawned thread that it should stop, so the
148 thread should check regularly
149 */
150
151 void signalQuit();
152
153 /**
154 Wait for a thread to stop. Should be called in the context of the spawning
155 thread. Returns false if the thread has not been started.
156 */
157
158 bool waitForQuit();
159
160 /**
161 check whether the thread is signalled to quit. Called in the context of the
162 spawned thread.
163 */
164
165 bool quitIsSignalled();
166
167 /**
168 Cleanly shut down this thread. Called in the context of the spawned thread.
169 */
170 void quit();
171
172 /**
173 Change the affinity mask for this thread. The mask is a platform
174 specific value.
175
176 On Windows, Linux, PS4, XboxOne and Switch platforms, each set mask bit represents
177 the index of a logical processor that the OS may schedule thread execution on.
178 Bits outside the range of valid logical processors may be ignored or cause
179 the function to return an error.
180
181 On Apple platforms, this function has no effect.
182
183 If the thread has not yet been started then the mask is stored
184 and applied when the thread is started.
185
186 If the thread has already been started then this method returns the
187 previous affinity mask on success, otherwise it returns zero.
188 */
189 uint32_t setAffinityMask(uint32_t mask);
190
191 static ThreadPriority::Enum getPriority(Id threadId);
192
193 /** Set thread priority. */
194 void setPriority(ThreadPriority::Enum prio);
195
196 /** set the thread's name */
197 void setName(const char* name);
198
199 /** Put the current thread to sleep for the given number of milliseconds */
200 static void sleep(uint32_t ms);
201
202 /** Yield the current thread's slot on the CPU */
203 static void yield();
204
205 /** Return the number of physical cores (does not include hyper-threaded cores), returns 0 on failure */
206 static uint32_t getNbPhysicalCores();
207
208 /**
209 Size of this class.
210 */
211 static uint32_t getSize();
212};
213
214/**
215Thread abstraction API
216*/
217template <typename Alloc = ReflectionAllocator<ThreadImpl> >
218class ThreadT : protected Alloc, public UserAllocated, public Runnable
219{
220 public:
221 typedef ThreadImpl::Id Id; // space for a pointer or an integer
222
223 /**
224 Construct (but do not start) the thread object. Executes in the context
225 of the spawning thread
226 */
227 ThreadT(const Alloc& alloc = Alloc()) : Alloc(alloc)
228 {
229 mImpl = reinterpret_cast<ThreadImpl*>(Alloc::allocate(ThreadImpl::getSize(), __FILE__, __LINE__));
230 PX_PLACEMENT_NEW(mImpl, ThreadImpl)();
231 }
232
233 /**
234 Construct and start the the thread, passing the given arg to the given fn. (pthread style)
235 */
236 ThreadT(ThreadImpl::ExecuteFn fn, void* arg, const char* name, const Alloc& alloc = Alloc()) : Alloc(alloc)
237 {
238 mImpl = reinterpret_cast<ThreadImpl*>(Alloc::allocate(ThreadImpl::getSize(), __FILE__, __LINE__));
239 PX_PLACEMENT_NEW(mImpl, ThreadImpl)(fn, arg, name);
240 }
241
242 /**
243 Deallocate all resources associated with the thread. Should be called in the
244 context of the spawning thread.
245 */
246 virtual ~ThreadT()
247 {
248 mImpl->~ThreadImpl();
249 Alloc::deallocate(mImpl);
250 }
251
252 /**
253 start the thread running. Called in the context of the spawning thread.
254 */
255
256 void start(uint32_t stackSize = ThreadImpl::getDefaultStackSize())
257 {
258 mImpl->start(stackSize, r: this);
259 }
260
261 /**
262 Violently kill the current thread. Blunt instrument, not recommended since
263 it can leave all kinds of things unreleased (stack, memory, mutexes...) Should
264 be called in the context of the spawning thread.
265 */
266
267 void kill()
268 {
269 mImpl->kill();
270 }
271
272 /**
273 The virtual execute() method is the user defined function that will
274 run in the new thread. Called in the context of the spawned thread.
275 */
276
277 virtual void execute(void)
278 {
279 }
280
281 /**
282 stop the thread. Signals the spawned thread that it should stop, so the
283 thread should check regularly
284 */
285
286 void signalQuit()
287 {
288 mImpl->signalQuit();
289 }
290
291 /**
292 Wait for a thread to stop. Should be called in the context of the spawning
293 thread. Returns false if the thread has not been started.
294 */
295
296 bool waitForQuit()
297 {
298 return mImpl->waitForQuit();
299 }
300
301 /**
302 check whether the thread is signalled to quit. Called in the context of the
303 spawned thread.
304 */
305
306 bool quitIsSignalled()
307 {
308 return mImpl->quitIsSignalled();
309 }
310
311 /**
312 Cleanly shut down this thread. Called in the context of the spawned thread.
313 */
314 void quit()
315 {
316 mImpl->quit();
317 }
318
319 uint32_t setAffinityMask(uint32_t mask)
320 {
321 return mImpl->setAffinityMask(mask);
322 }
323
324 static ThreadPriority::Enum getPriority(ThreadImpl::Id threadId)
325 {
326 return ThreadImpl::getPriority(threadId);
327 }
328
329 /** Set thread priority. */
330 void setPriority(ThreadPriority::Enum prio)
331 {
332 mImpl->setPriority(prio);
333 }
334
335 /** set the thread's name */
336 void setName(const char* name)
337 {
338 mImpl->setName(name);
339 }
340
341 /** Put the current thread to sleep for the given number of milliseconds */
342 static void sleep(uint32_t ms)
343 {
344 ThreadImpl::sleep(ms);
345 }
346
347 /** Yield the current thread's slot on the CPU */
348 static void yield()
349 {
350 ThreadImpl::yield();
351 }
352
353 static uint32_t getDefaultStackSize()
354 {
355 return ThreadImpl::getDefaultStackSize();
356 }
357
358 static ThreadImpl::Id getId()
359 {
360 return ThreadImpl::getId();
361 }
362
363 static uint32_t getNbPhysicalCores()
364 {
365 return ThreadImpl::getNbPhysicalCores();
366 }
367
368 private:
369 class ThreadImpl* mImpl;
370};
371
372typedef ThreadT<> Thread;
373
374PX_FOUNDATION_API uint32_t TlsAlloc();
375PX_FOUNDATION_API void TlsFree(uint32_t index);
376PX_FOUNDATION_API void* TlsGet(uint32_t index);
377PX_FOUNDATION_API size_t TlsGetValue(uint32_t index);
378PX_FOUNDATION_API uint32_t TlsSet(uint32_t index, void* value);
379PX_FOUNDATION_API uint32_t TlsSetValue(uint32_t index, size_t value);
380
381} // namespace shdfnd
382} // namespace physx
383
384#endif // #ifndef PSFOUNDATION_PSTHREAD_H
385

source code of qtquick3dphysics/src/3rdparty/PhysX/source/foundation/include/PsThread.h