ReXGlue SDK
Loading...
Searching...
No Matches
kernel_thread.h
Go to the documentation of this file.
1
13
14#pragma once
15
16#include <array>
17#include <atomic>
18#include <chrono>
19#include <cstddef>
20#include <memory>
21#include <mutex>
22#include <string>
23#include <string_view>
24
25#include <rex/assert.h>
27#include <rex/platform.h>
29#include <rex/kernel/thread_state.h>
33#include <rex/platform/thread.h>
34#include <rex/types.h>
35#include <rex/utility.h>
36
37namespace rex {
38namespace kernel {
39class TitleRuntime;
40} // namespace kernel
41} // namespace rex
42
43namespace rex::kernel {
44
45class ThreadRegistry;
46
48struct ThreadRef : public rex::NonCopyable {
49 ThreadRef(u32 thread_id_in, ThreadRegistry* registry_in)
50 : thread_id(thread_id_in), registry(registry_in) {}
53
55 ThreadRegistry* registry;
56};
57
60 public:
61 virtual ~ICallingThread() = default;
62
63 virtual u32 GetLastError() = 0;
64
65 virtual void SetLastError(u32 error_code) = 0;
66
68 virtual bool IsMainThread() const = 0;
69};
70
73 public:
75 static constexpr u32 kStackAddressRangeBegin = 0x70000000;
77 static constexpr u32 kStackAddressRangeEnd = 0x7F000000;
78
87
99 KernelThread(TitleRuntime& runtime, u32 stack_size, u32 xapi_thread_startup, u32 start_address,
100 u32 start_context, u32 creation_flags, bool guest_thread, bool main_thread = false,
101 u32 title_process = 0);
102
108 KernelThread(TitleRuntime& runtime, u32 stack_size, u32 creation_flags,
109 rex::MoveOnlyFunction<int()> host_fn);
112
113 static bool IsInThread(const KernelThread* other);
114
115 static bool IsInThread();
116
117 static KernelThread* GetCallingThread();
118
119 static u32 GetCurrentThreadHandle();
120
124 static void CheckStop();
125
132 static bool IsStopPending();
133
135 static void SleepFor(std::chrono::microseconds duration);
136
140 static void WriteKernelTime();
141
142 TitleRuntime& GetRuntime() const { return *runtime_; }
143
144 kernel::GuestAddressSpace* GetAddressSpace() const;
145
149 X_HANDLE GetHandle() const { return handle_; }
150
151 u32 GetGuestObject() const { return guest_object_ptr_; }
152
154 template <typename T>
156 return GetAddressSpace()->TranslateVirtual<T*>(guest_object_ptr_);
157 }
158
159 const std::string& GetName() const { return thread_name_; }
160
165 std::string_view GetCrashName() const {
166 return {crash_name_.data(), crash_name_length_.load(std::memory_order_acquire)};
167 }
168
169 const CreationParams* GetCreationParams() const { return &creation_params_; }
170
171 u32 GetTLSPtr() const { return tls_static_address_; }
172
173 u32 GetPCRPtr() const { return pcr_address_; }
174
175 bool IsGuestThread() const { return guest_thread_; }
176
177 bool IsMainThread() const override { return main_thread_; }
178
179 bool IsRunning() const { return running_; }
180
181 u32 GetThreadID() const { return thread_id_; }
182
183 u32 GetLastError() override;
184
185 void SetLastError(u32 error_code) override;
186
190 void SetName(const std::string_view name);
191
195 [[noreturn]] void Exit(int exit_code);
196
198 void RequestStop(i32 exit_code = 0);
199
205 bool ForceStop();
206
207 rex::platform::Fiber* GetMainFiber() const { return main_fiber_; }
208
209 void SetMainFiber(rex::platform::Fiber* fiber) { main_fiber_ = fiber; }
210
213
216
217 void DeliverAPCs();
218
225
226 void EnqueueAPC(u32 normal_routine, u32 normal_context, u32 arg1, u32 arg2);
227
228 i32 GetPriority() const { return priority_; }
229
230 i32 GetHostPriority();
231
232 void SetPriority(i32 increment);
233
241 bool SetAffinity(u32 affinity);
242
243 u8 GetActiveCPU() const;
244
245 void SetActiveCPU(u8 cpu_index);
246
251 bool GetTLSValue(u32 slot, u32* value_out) const;
252
256 bool SetTLSValue(u32 slot, u32 value);
257
258 u32 GetSuspendCount();
259
264 X_STATUS Resume(u32* out_suspend_count = nullptr);
265
270 X_STATUS Suspend(u32* out_suspend_count = nullptr);
271
279 X_STATUS Delay(u32 processor_mode, u32 alertable, u64 interval) const;
280
281 rex::platform::Thread* GetThread() { return thread_.get(); }
282
283 kernel::ThreadState* GetThreadState() { return thread_state_.get(); }
284
286
287 protected:
288 void FreeStack();
289 void InitializeGuestObject();
290
291 void RundownAPCs();
292 void CallThreadNotifyRoutines(bool create);
293
294 CreationParams creation_params_ = {0, 0, 0, 0, 0, 0};
295
296 u32 thread_id_ = 0;
300 u32 tls_static_address_ = 0;
301 u32 tls_dynamic_address_ = 0;
303 std::atomic<u32> tls_slot_count_{0};
304 u32 pcr_address_ = 0;
305 u32 stack_alloc_base_ = 0;
307 u32 stack_base_ = 0;
308 u32 stack_limit_ = 0;
309 bool guest_thread_ = false;
310 bool main_thread_ = false;
311 std::atomic<bool> running_{false};
313 std::atomic<bool> exiting_{false};
315 std::atomic<i32> stop_exit_code_{0};
317 std::mutex stop_mutex_;
319 bool stop_requested_ = false;
320
321 std::string thread_name_;
323 std::array<char, 64> crash_name_{};
324 std::atomic<u8> crash_name_length_{0};
325 std::unique_ptr<kernel::ThreadState> thread_state_;
326
327 i32 priority_ = 0;
328
329 struct SuspendWait;
334 std::unique_ptr<SuspendWait> suspend_wait_;
336 std::atomic<bool> suspend_deferred_{false};
337
338 std::mutex thread_lock_;
339
340 std::unique_ptr<rex::platform::Thread> thread_ = nullptr;
341 rex::platform::Fiber* main_fiber_ = nullptr;
342
343 private:
344 friend class ThreadRegistry;
345
351 X_STATUS Create();
352
354 void Start();
355
357 void Abandon();
358 void SetHandle(X_HANDLE handle) { handle_ = handle; }
359 void SetGuestObject(u32 address) { guest_object_ptr_ = address; }
360 int Execute();
361 void Finish(int exit_code);
362 [[noreturn]] static void ThrowStop();
364 bool ShouldStop() const;
366 void WaitForResume(std::unique_lock<std::mutex>& lock);
367 void ReleaseSelf();
368
370 void ReleaseReference();
371
377 u32 SelfSuspend();
378
380 void TakeDeferredSuspend();
381
386 u32 GetProcessAddress() const;
387
388 void WriteExitState(u32 exit_code);
389
390 TitleRuntime* runtime_;
391 ThreadRegistry* registry_ = nullptr;
392 X_HANDLE handle_ = 0;
393 u32 guest_object_ptr_ = 0;
394 rex::MoveOnlyFunction<int()> host_fn_;
395 std::atomic<bool> released_{false};
396 std::atomic<bool> abandoned_{false};
397 bool exited_ = false;
398 bool handles_closed_ = false;
399};
400
401} // namespace rex::kernel
Definition utility.h:37
Definition heap.h:594
Definition kernel_thread.h:59
virtual bool IsMainThread() const =0
KernelThread(TitleRuntime &runtime, u32 stack_size, u32 xapi_thread_startup, u32 start_address, u32 start_context, u32 creation_flags, bool guest_thread, bool main_thread=false, u32 title_process=0)
T * GetGuestObject()
Definition kernel_thread.h:155
bool SetTLSValue(u32 slot, u32 value)
static void WriteKernelTime()
static void SleepFor(std::chrono::microseconds duration)
static constexpr u32 kStackAddressRangeEnd
Definition kernel_thread.h:77
std::string_view GetCrashName() const
Definition kernel_thread.h:165
X_STATUS Delay(u32 processor_mode, u32 alertable, u64 interval) const
bool GetTLSValue(u32 slot, u32 *value_out) const
PinCount pins
Definition kernel_thread.h:285
std::atomic< bool > suspend_deferred_
Definition kernel_thread.h:336
void RequestStop(i32 exit_code=0)
u32 scratch_size_
Definition kernel_thread.h:299
X_STATUS Suspend(u32 *out_suspend_count=nullptr)
X_HANDLE GetHandle() const
Definition kernel_thread.h:149
void Exit(int exit_code)
bool IsMainThread() const override
Definition kernel_thread.h:177
void SetName(const std::string_view name)
X_STATUS Resume(u32 *out_suspend_count=nullptr)
KernelThread(TitleRuntime &runtime, u32 stack_size, u32 creation_flags, rex::MoveOnlyFunction< int()> host_fn)
std::atomic< bool > exiting_
Definition kernel_thread.h:313
std::atomic< i32 > stop_exit_code_
Definition kernel_thread.h:315
bool stop_requested_
Definition kernel_thread.h:319
std::array< char, 64 > crash_name_
Definition kernel_thread.h:323
std::unique_ptr< SuspendWait > suspend_wait_
Definition kernel_thread.h:334
bool SetAffinity(u32 affinity)
std::mutex stop_mutex_
Definition kernel_thread.h:317
std::atomic< u32 > tls_slot_count_
Definition kernel_thread.h:303
u32 stack_base_
Definition kernel_thread.h:307
static bool IsStopPending()
std::mutex thread_lock_
Definition kernel_thread.h:338
static constexpr u32 kStackAddressRangeBegin
Definition kernel_thread.h:75
u32 scratch_address_
Definition kernel_thread.h:298
Definition object.h:150
Definition thread_state.h:40
Definition title_runtime.h:85
Definition thread.h:155
Virtual memory flags and typed guest pointers.
Guest list and spin lock structures.
Definition export.h:24
u32 X_STATUS
Definition status.h:23
Definition app.h:36
typename detail::MoveOnlyFunctionFor< Signature >::type MoveOnlyFunction
Definition utility.h:254
Platform flags, packing macros and export markers.
#define REX_KERNEL_API
Definition platform.h:297
Definition kernel_thread.h:79
u32 title_process
Definition kernel_thread.h:85
u32 xapi_thread_startup
Definition kernel_thread.h:81
u32 start_context
Definition kernel_thread.h:83
u32 stack_size
Definition kernel_thread.h:80
u32 start_address
Definition kernel_thread.h:82
u32 creation_flags
Definition kernel_thread.h:84
u32 thread_id
Definition kernel_thread.h:54
ThreadRegistry * registry
Definition kernel_thread.h:55
Definition thread.h:307
Integer types, byte order wrappers and size literals.
Move only function, const propagating pointer and scope guard.