1/**
2 * @file os.h
3 * @brief Operating System implementations.
4 */
5
6#pragma once
7
8#include <type_traits>
9
10#include <nn/time.h>
11#include <nn/types.h>
12
13#include <nn/os/detail/os_InternalCriticalSection.h>
14#include <nn/os/os_MessageQueueTypes.h>
15#include <nn/os/os_Mutex.h>
16#include <nn/os/os_MutexTypes.h>
17#include <nn/os/os_ThreadTypes.h>
18
19namespace nn {
20namespace os {
21
22namespace detail {
23
24class MultiWaitObjectList;
25struct InterProcessEventType {
26 enum State {
27 State_NotInitialized = 0,
28 State_Initialized = 1,
29 };
30
31 nn::os::detail::InterProcessEventType* _x0;
32 nn::os::detail::InterProcessEventType* _x8;
33 bool shouldAutoClear;
34 u8 state;
35 bool isReadableHandleManaged;
36 bool isWritableHandleManaged;
37 u32 readableHandle;
38 u32 writableHandle;
39};
40} // namespace detail
41
42typedef u64 Tick;
43
44struct LightEventType {
45 std::aligned_storage_t<0xc, 4> storage;
46};
47
48struct EventType {
49 util::TypedStorage<detail::MultiWaitObjectList, 16, 8> _multiWaitObjectList;
50 bool _signalState;
51 bool _initiallySignaled;
52 uint8_t _clearMode;
53 uint8_t _state;
54 uint32_t _broadcastCounterLower;
55 uint32_t _broadcastCounterUpper;
56 detail::InternalCriticalSectionStorage _csEvent;
57 detail::InternalConditionVariableStorage _cvSignaled;
58};
59static_assert(std::is_trivial<EventType>::value, "EventType non trivial");
60typedef EventType Event;
61
62enum EventClearMode { EventClearMode_ManualClear, EventClearMode_AutoClear };
63
64struct ConditionVariableType {};
65
66struct SemaphoreType {
67 std::aligned_storage_t<0x28, 8> storage;
68};
69
70struct SystemEventType {
71 enum State {
72 State_NotInitialized = 0,
73 State_InitializedAsEvent = 1,
74 State_InitializedAsInterProcessEvent = 2,
75 };
76
77 union {
78 nn::os::EventType event;
79 nn::os::detail::InterProcessEventType interProcessEvent;
80 };
81 u8 state;
82};
83struct SystemEvent {
84 SystemEventType m_SystemEventType;
85};
86
87// ARG
88void SetHostArgc(s32);
89s32 GetHostArgc();
90void SetHostArgv(char**);
91char** GetHostArgv();
92
93// MEMORY
94void InitializeVirtualAddressMemory();
95Result AllocateAddressRegion(u64*, u64);
96Result AllocateMemory(u64*, u64);
97Result AllocateMemoryPages(u64, u64);
98void AllocateMemoryBlock(u64*, u64);
99void FreeMemoryBlock(u64, u64);
100void SetMemoryHeapSize(u64);
101
102// QUEUE
103void InitializeMessageQueue(nn::os::MessageQueueType*, u64* buf, u64 queueCount);
104void FinalizeMessageQueue(nn::os::MessageQueueType*);
105
106bool TrySendMessageQueue(MessageQueueType*, u64);
107void SendMessageQueue(MessageQueueType*, u64);
108bool TimedSendMessageQueue(MessageQueueType*, u64, nn::TimeSpan);
109
110bool TryReceiveMessageQueue(u64* out, MessageQueueType*);
111void ReceiveMessageQueue(u64* out, MessageQueueType*);
112bool TimedReceiveMessageQueue(u64* out, MessageQueueType*, nn::TimeSpan);
113
114bool TryPeekMessageQueue(u64*, MessageQueueType const*);
115void PeekMessageQueue(u64*, MessageQueueType const*);
116bool TimedPeekMessageQueue(u64*, MessageQueueType const*);
117
118bool TryJamMessageQueue(nn::os::MessageQueueType*, u64);
119void JamMessageQueue(nn::os::MessageQueueType*, u64);
120bool TimedJamMessageQueue(nn::os::MessageQueueType*, u64, nn::TimeSpan);
121
122// CONDITION VARIABLE
123void InitializeConditionVariable(ConditionVariableType*);
124void FinalizeConditionVariable(ConditionVariableType*);
125
126void SignalConditionVariable(ConditionVariableType*);
127void BroadcastConditionVariable(ConditionVariableType*);
128void WaitConditionVariable(ConditionVariableType*);
129u8 TimedWaitConditionVariable(ConditionVariableType*, nn::os::MutexType*, nn::TimeSpan);
130
131// THREAD
132Result CreateThread(nn::os::ThreadType*, void (*)(void*), void* arg, void* srcStack, u64 stackSize,
133 s32 priority, s32 coreNum);
134Result CreateThread(nn::os::ThreadType*, void (*)(void*), void* arg, void* srcStack, u64 stackSize,
135 s32 priority);
136void DestroyThread(nn::os::ThreadType*);
137void StartThread(nn::os::ThreadType*);
138void SetThreadName(nn::os::ThreadType*, char const* threadName);
139void SetThreadNamePointer(nn::os::ThreadType*, char const*);
140char* GetThreadNamePointer(nn::os::ThreadType const*);
141nn::os::ThreadType* GetCurrentThread();
142void GetCurrentStackInfo(uintptr_t* stack_addr, size_t* stack_size);
143s32 ChangeThreadPriority(nn::os::ThreadType* thread, s32 priority);
144s32 GetThreadPriority(nn::os::ThreadType const* thread);
145u64 GetThreadId(const nn::os::ThreadType* thread);
146void YieldThread();
147void SuspendThread(nn::os::ThreadType*);
148void ResumeThread(nn::os::ThreadType*);
149void SleepThread(nn::TimeSpan);
150void WaitThread(nn::os::ThreadType*);
151void SetThreadCoreMask(nn::os::ThreadType*, int, u64 mask);
152
153// EVENTS
154void InitializeEvent(EventType*, bool initiallySignaled, EventClearMode eventClearMode);
155void FinalizeEvent(EventType*);
156void SignalEvent(EventType*);
157void WaitEvent(EventType*);
158bool TryWaitEvent(EventType*);
159bool TimedWaitEvent(EventType*, nn::TimeSpan);
160void ClearEvent(EventType*);
161
162// LIGHT EVENTS
163void InitializeLightEvent(LightEventType*, bool initiallySignaled, EventClearMode eventClearMode);
164void FinalizeLightEvent(LightEventType*);
165void SignalLightEvent(LightEventType*);
166void WaitLightEvent(LightEventType*);
167bool TimedWaitLightEvent(LightEventType*, nn::TimeSpan);
168void ClearLightEvent(LightEventType*);
169
170TimeSpan ConvertToTimeSpan(Tick ticks);
171
172// SEMAPHORES
173void InitializeSemaphore(SemaphoreType* semaphore, s32 initial_count, s32 max_count);
174void FinalizeSemaphore(SemaphoreType* semaphore);
175void AcquireSemaphore(SemaphoreType* semaphore);
176bool TryAcquireSemaphore(SemaphoreType* semaphore);
177void ReleaseSemaphore(SemaphoreType* semaphore);
178
179// EXCEPTION HANDLING
180typedef union {
181 u64 x; ///< 64-bit AArch64 register view.
182 u32 w; ///< 32-bit AArch64 register view.
183 u32 r; ///< AArch32 register view.
184} CpuRegister;
185/// Armv8 NEON register.
186
187typedef union {
188 u128 v; ///< 128-bit vector view.
189 double d; ///< 64-bit double-precision view.
190 float s; ///< 32-bit single-precision view.
191} FpuRegister;
192
193struct UserExceptionInfo {
194 u32 ErrorDescription; ///< See \ref ThreadExceptionDesc.
195 u32 pad[3];
196
197 CpuRegister CpuRegisters[29]; ///< GPRs 0..28. Note: also contains AArch32 registers.
198 CpuRegister FP; ///< Frame pointer.
199 CpuRegister LR; ///< Link register.
200 CpuRegister SP; ///< Stack pointer.
201 CpuRegister PC; ///< Program counter (elr_el1).
202
203 u64 padding;
204
205 FpuRegister FpuRegisters[32]; ///< 32 general-purpose NEON registers.
206
207 u32 PState; ///< pstate & 0xFF0FFE20
208 u32 AFSR0;
209 u32 AFSR1;
210 u32 ESR;
211
212 CpuRegister FAR; ///< Fault Address Register.
213};
214void SetUserExceptionHandler(void (*)(UserExceptionInfo*), void*, ulong, UserExceptionInfo*);
215
216// OTHER
217void GenerateRandomBytes(void*, u64);
218nn::os::Tick GetSystemTick();
219nn::os::Tick GetSystemTickFrequency();
220u64 GetThreadAvailableCoreMask();
221void SetMemoryHeapSize(u64 size);
222
223// Thread-local storage
224struct TlsSlot {
225 u32 slot;
226};
227Result AllocateTlsSlot(TlsSlot* slot_out, void (*)(u64));
228void FreeTlsSlot(TlsSlot slot);
229u64 GetTlsValue(TlsSlot slot);
230void SetTlsValue(TlsSlot slot, u64 value);
231u32 GetCurrentCoreNumber();
232
233namespace detail {
234extern s32 g_CommandLineParameter;
235extern char** g_CommandLineParameterArgv;
236} // namespace detail
237} // namespace os
238} // namespace nn
239