diff options
| author | 2014-05-22 18:50:36 -0400 | |
|---|---|---|
| committer | 2014-05-22 18:50:36 -0400 | |
| commit | 14bd37c5dc67c7777d4bea8d996bf2dfd8c7bdcc (patch) | |
| tree | 1849fdeba7de9c6bd98b42c31a6c853af487acea /src/core | |
| parent | APT_U: added a debug log on calling GetLockHandle (diff) | |
| download | yuzu-14bd37c5dc67c7777d4bea8d996bf2dfd8c7bdcc.tar.gz yuzu-14bd37c5dc67c7777d4bea8d996bf2dfd8c7bdcc.tar.xz yuzu-14bd37c5dc67c7777d4bea8d996bf2dfd8c7bdcc.zip | |
thread: moved ThreadStatus/WaitType to header, added support for arg on CreateThread, added correct CPSR reset
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 49 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.h | 26 |
2 files changed, 40 insertions, 35 deletions
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index ef705e327..934ca87c4 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp | |||
| @@ -21,27 +21,6 @@ | |||
| 21 | 21 | ||
| 22 | namespace Kernel { | 22 | namespace Kernel { |
| 23 | 23 | ||
| 24 | enum ThreadStatus { | ||
| 25 | THREADSTATUS_RUNNING = 1, | ||
| 26 | THREADSTATUS_READY = 2, | ||
| 27 | THREADSTATUS_WAIT = 4, | ||
| 28 | THREADSTATUS_SUSPEND = 8, | ||
| 29 | THREADSTATUS_DORMANT = 16, | ||
| 30 | THREADSTATUS_DEAD = 32, | ||
| 31 | THREADSTATUS_WAITSUSPEND = THREADSTATUS_WAIT | THREADSTATUS_SUSPEND | ||
| 32 | }; | ||
| 33 | |||
| 34 | enum WaitType { | ||
| 35 | WAITTYPE_NONE, | ||
| 36 | WAITTYPE_SLEEP, | ||
| 37 | WAITTYPE_SEMA, | ||
| 38 | WAITTYPE_EVENTFLAG, | ||
| 39 | WAITTYPE_THREADEND, | ||
| 40 | WAITTYPE_VBLANK, | ||
| 41 | WAITTYPE_MUTEX, | ||
| 42 | WAITTYPE_SYNCH, | ||
| 43 | }; | ||
| 44 | |||
| 45 | class Thread : public Kernel::Object { | 24 | class Thread : public Kernel::Object { |
| 46 | public: | 25 | public: |
| 47 | 26 | ||
| @@ -101,16 +80,18 @@ void __SaveContext(ThreadContext& ctx) { | |||
| 101 | } | 80 | } |
| 102 | 81 | ||
| 103 | /// Loads a CPU context | 82 | /// Loads a CPU context |
| 104 | void __LoadContext(const ThreadContext& ctx) { | 83 | void __LoadContext(ThreadContext& ctx) { |
| 105 | Core::g_app_core->LoadContext(ctx); | 84 | Core::g_app_core->LoadContext(ctx); |
| 106 | } | 85 | } |
| 107 | 86 | ||
| 108 | /// Resets a thread | 87 | /// Resets a thread |
| 109 | void __ResetThread(Thread* t, s32 lowest_priority) { | 88 | void __ResetThread(Thread* t, u32 arg, s32 lowest_priority) { |
| 110 | memset(&t->context, 0, sizeof(ThreadContext)); | 89 | memset(&t->context, 0, sizeof(ThreadContext)); |
| 111 | 90 | ||
| 91 | t->context.cpu_registers[0] = arg; | ||
| 112 | t->context.pc = t->entry_point; | 92 | t->context.pc = t->entry_point; |
| 113 | t->context.sp = t->stack_top; | 93 | t->context.sp = t->stack_top; |
| 94 | t->context.cpsr = 0x1F; // Usermode | ||
| 114 | 95 | ||
| 115 | if (t->current_priority < lowest_priority) { | 96 | if (t->current_priority < lowest_priority) { |
| 116 | t->current_priority = t->initial_priority; | 97 | t->current_priority = t->initial_priority; |
| @@ -201,7 +182,7 @@ Thread* __NextThread() { | |||
| 201 | } | 182 | } |
| 202 | 183 | ||
| 203 | /// Puts a thread in the wait state for the given type/reason | 184 | /// Puts a thread in the wait state for the given type/reason |
| 204 | void __WaitCurThread(WaitType wait_type, const char* reason) { | 185 | void WaitCurThread(WaitType wait_type, const char* reason) { |
| 205 | Thread* t = __GetCurrentThread(); | 186 | Thread* t = __GetCurrentThread(); |
| 206 | t->wait_type = wait_type; | 187 | t->wait_type = wait_type; |
| 207 | __ChangeThreadState(t, ThreadStatus(THREADSTATUS_WAIT | (t->status & THREADSTATUS_SUSPEND))); | 188 | __ChangeThreadState(t, ThreadStatus(THREADSTATUS_WAIT | (t->status & THREADSTATUS_SUSPEND))); |
| @@ -248,7 +229,7 @@ Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 prio | |||
| 248 | } | 229 | } |
| 249 | 230 | ||
| 250 | /// Creates a new thread - wrapper for external user | 231 | /// Creates a new thread - wrapper for external user |
| 251 | Handle CreateThread(const char* name, u32 entry_point, s32 priority, s32 processor_id, | 232 | Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s32 processor_id, |
| 252 | u32 stack_top, int stack_size) { | 233 | u32 stack_top, int stack_size) { |
| 253 | if (name == NULL) { | 234 | if (name == NULL) { |
| 254 | ERROR_LOG(KERNEL, "CreateThread(): NULL name"); | 235 | ERROR_LOG(KERNEL, "CreateThread(): NULL name"); |
| @@ -275,6 +256,8 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, s32 process | |||
| 275 | Thread* t = CreateThread(handle, name, entry_point, priority, processor_id, stack_top, | 256 | Thread* t = CreateThread(handle, name, entry_point, priority, processor_id, stack_top, |
| 276 | stack_size); | 257 | stack_size); |
| 277 | 258 | ||
| 259 | __ResetThread(t, arg, 0); | ||
| 260 | |||
| 278 | HLE::EatCycles(32000); | 261 | HLE::EatCycles(32000); |
| 279 | 262 | ||
| 280 | // This won't schedule to the new thread, but it may to one woken from eating cycles. | 263 | // This won't schedule to the new thread, but it may to one woken from eating cycles. |
| @@ -299,7 +282,7 @@ Handle SetupMainThread(s32 priority, int stack_size) { | |||
| 299 | Thread* t = CreateThread(handle, "main", Core::g_app_core->GetPC(), priority, | 282 | Thread* t = CreateThread(handle, "main", Core::g_app_core->GetPC(), priority, |
| 300 | THREADPROCESSORID_0, Memory::SCRATCHPAD_VADDR_END, stack_size); | 283 | THREADPROCESSORID_0, Memory::SCRATCHPAD_VADDR_END, stack_size); |
| 301 | 284 | ||
| 302 | __ResetThread(t, 0); | 285 | __ResetThread(t, 0, 0); |
| 303 | 286 | ||
| 304 | // If running another thread already, set it to "ready" state | 287 | // If running another thread already, set it to "ready" state |
| 305 | Thread* cur = __GetCurrentThread(); | 288 | Thread* cur = __GetCurrentThread(); |
| @@ -317,18 +300,16 @@ Handle SetupMainThread(s32 priority, int stack_size) { | |||
| 317 | 300 | ||
| 318 | /// Reschedules to the next available thread (call after current thread is suspended) | 301 | /// Reschedules to the next available thread (call after current thread is suspended) |
| 319 | void Reschedule(const char* reason) { | 302 | void Reschedule(const char* reason) { |
| 303 | Thread* prev = __GetCurrentThread(); | ||
| 320 | Thread* next = __NextThread(); | 304 | Thread* next = __NextThread(); |
| 321 | if (next > 0) { | 305 | if (next > 0) { |
| 322 | __SwitchContext(next, reason); | 306 | __SwitchContext(next, reason); |
| 323 | } | ||
| 324 | } | ||
| 325 | 307 | ||
| 326 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 308 | // Hack - automatically change previous thread (which would have been in "wait" state) to |
| 327 | 309 | // "ready" state, so that we can immediately resume to it when new thread yields. FixMe to | |
| 328 | /// Put current thread in a wait state - on WaitSynchronization | 310 | // actually wait for whatever event it is supposed to be waiting on. |
| 329 | void WaitThread_Synchronization() { | 311 | __ChangeReadyState(prev, true); |
| 330 | // TODO(bunnei): Just a placeholder function for now... FixMe | 312 | } |
| 331 | __WaitCurThread(WAITTYPE_SYNCH, "waitSynchronization called"); | ||
| 332 | } | 313 | } |
| 333 | 314 | ||
| 334 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 315 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 0d1fe19bf..82bf16082 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h | |||
| @@ -20,10 +20,31 @@ enum ThreadProcessorId { | |||
| 20 | THREADPROCESSORID_ALL = 0xFFFFFFFC, ///< Enables both cores | 20 | THREADPROCESSORID_ALL = 0xFFFFFFFC, ///< Enables both cores |
| 21 | }; | 21 | }; |
| 22 | 22 | ||
| 23 | enum ThreadStatus { | ||
| 24 | THREADSTATUS_RUNNING = 1, | ||
| 25 | THREADSTATUS_READY = 2, | ||
| 26 | THREADSTATUS_WAIT = 4, | ||
| 27 | THREADSTATUS_SUSPEND = 8, | ||
| 28 | THREADSTATUS_DORMANT = 16, | ||
| 29 | THREADSTATUS_DEAD = 32, | ||
| 30 | THREADSTATUS_WAITSUSPEND = THREADSTATUS_WAIT | THREADSTATUS_SUSPEND | ||
| 31 | }; | ||
| 32 | |||
| 33 | enum WaitType { | ||
| 34 | WAITTYPE_NONE, | ||
| 35 | WAITTYPE_SLEEP, | ||
| 36 | WAITTYPE_SEMA, | ||
| 37 | WAITTYPE_EVENTFLAG, | ||
| 38 | WAITTYPE_THREADEND, | ||
| 39 | WAITTYPE_VBLANK, | ||
| 40 | WAITTYPE_MUTEX, | ||
| 41 | WAITTYPE_SYNCH, | ||
| 42 | }; | ||
| 43 | |||
| 23 | namespace Kernel { | 44 | namespace Kernel { |
| 24 | 45 | ||
| 25 | /// Creates a new thread - wrapper for external user | 46 | /// Creates a new thread - wrapper for external user |
| 26 | Handle CreateThread(const char* name, u32 entry_point, s32 priority, s32 processor_id, | 47 | Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s32 processor_id, |
| 27 | u32 stack_top, int stack_size=Kernel::DEFAULT_STACK_SIZE); | 48 | u32 stack_top, int stack_size=Kernel::DEFAULT_STACK_SIZE); |
| 28 | 49 | ||
| 29 | /// Sets up the primary application thread | 50 | /// Sets up the primary application thread |
| @@ -32,6 +53,9 @@ Handle SetupMainThread(s32 priority, int stack_size=Kernel::DEFAULT_STACK_SIZE); | |||
| 32 | /// Reschedules to the next available thread (call after current thread is suspended) | 53 | /// Reschedules to the next available thread (call after current thread is suspended) |
| 33 | void Reschedule(const char* reason); | 54 | void Reschedule(const char* reason); |
| 34 | 55 | ||
| 56 | /// Puts a thread in the wait state for the given type/reason | ||
| 57 | void WaitCurThread(WaitType wait_type, const char* reason); | ||
| 58 | |||
| 35 | /// Resumes a thread from waiting by marking it as "ready" | 59 | /// Resumes a thread from waiting by marking it as "ready" |
| 36 | void ResumeThreadFromWait(Handle handle); | 60 | void ResumeThreadFromWait(Handle handle); |
| 37 | 61 | ||