diff options
author | bunnei <ericbunnie@gmail.com> | 2014-05-21 01:37:46 +0200 |
---|---|---|
committer | bunnei <ericbunnie@gmail.com> | 2014-05-21 01:37:46 +0200 |
commit | 75c6d2a8fa3547946227094af6c179e5ccba0e1e (patch) | |
tree | 6199164fdc1745d6b12333b0b2efc269e8c7ee5d | |
parent | ARM_Interpreter/ARM_Interface: Fixed member variable naming to be consistent with style guide (diff) | |
download | yuzu-75c6d2a8fa3547946227094af6c179e5ccba0e1e.tar yuzu-75c6d2a8fa3547946227094af6c179e5ccba0e1e.tar.gz yuzu-75c6d2a8fa3547946227094af6c179e5ccba0e1e.tar.bz2 yuzu-75c6d2a8fa3547946227094af6c179e5ccba0e1e.tar.lz yuzu-75c6d2a8fa3547946227094af6c179e5ccba0e1e.tar.xz yuzu-75c6d2a8fa3547946227094af6c179e5ccba0e1e.tar.zst yuzu-75c6d2a8fa3547946227094af6c179e5ccba0e1e.zip |
-rw-r--r-- | src/core/hle/kernel/kernel.cpp | 6 | ||||
-rw-r--r-- | src/core/hle/kernel/thread.cpp | 184 | ||||
-rw-r--r-- | src/core/hle/kernel/thread.h | 26 | ||||
-rw-r--r-- | src/core/hle/svc.cpp | 4 |
4 files changed, 117 insertions, 103 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index b1fdffde5..45e36173c 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -132,11 +132,11 @@ Object* ObjectPool::CreateByIDType(int type) { } void Init() { - __KernelThreadingInit(); + Kernel::ThreadingInit(); } void Shutdown() { - __KernelThreadingShutdown(); + Kernel::ThreadingShutdown(); } } // namespace @@ -147,7 +147,7 @@ bool __KernelLoadExec(u32 entry_point) { Core::g_app_core->SetPC(entry_point); // 0x30 is the typical main thread priority I've seen used so far - Handle thread_id = __KernelSetupMainThread(0x30); + Handle thread_id = Kernel::SetupMainThread(0x30); return true; } diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index b3d306c53..7b4f0ea47 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -19,7 +19,7 @@ #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/thread.h" -// Enums +namespace Kernel { enum ThreadStatus { THREADSTATUS_RUNNING = 1, @@ -81,33 +81,32 @@ std::vector<Handle> g_thread_queue; Common::ThreadQueueList<Handle> g_thread_ready_queue; Handle g_current_thread_handle; - Thread* g_current_thread; +/// Gets the current thread inline Thread* __GetCurrentThread() { return g_current_thread; } +/// Sets the current thread inline void __SetCurrentThread(Thread* t) { g_current_thread = t; g_current_thread_handle = t->GetHandle(); } -//////////////////////////////////////////////////////////////////////////////////////////////////// - /// Saves the current CPU context -void __KernelSaveContext(ThreadContext& ctx) { +void __SaveContext(ThreadContext& ctx) { Core::g_app_core->SaveContext(ctx); } /// Loads a CPU context -void __KernelLoadContext(const ThreadContext& ctx) { +void __LoadContext(const ThreadContext& ctx) { Core::g_app_core->LoadContext(ctx); } /// Resets a thread -void __KernelResetThread(Thread* t, s32 lowest_priority) { +void __ResetThread(Thread* t, s32 lowest_priority) { memset(&t->context, 0, sizeof(ThreadContext)); t->context.pc = t->entry_point; @@ -121,7 +120,7 @@ void __KernelResetThread(Thread* t, s32 lowest_priority) { } /// Change a thread to "ready" state -void __KernelChangeReadyState(Thread* t, bool ready) { +void __ChangeReadyState(Thread* t, bool ready) { Handle handle = t->GetHandle(); if (t->IsReady()) { if (!ready) { @@ -138,11 +137,11 @@ void __KernelChangeReadyState(Thread* t, bool ready) { } /// Changes a threads state -void __KernelChangeThreadState(Thread* t, ThreadStatus new_status) { +void __ChangeThreadState(Thread* t, ThreadStatus new_status) { if (!t || t->status == new_status) { return; } - __KernelChangeReadyState(t, (new_status & THREADSTATUS_READY) != 0); + __ChangeReadyState(t, (new_status & THREADSTATUS_READY) != 0); t->status = new_status; if (new_status == THREADSTATUS_WAIT) { @@ -153,16 +152,75 @@ void __KernelChangeThreadState(Thread* t, ThreadStatus new_status) { } /// Calls a thread by marking it as "ready" (note: will not actually execute until current thread yields) -void __KernelCallThread(Thread* t) { +void __CallThread(Thread* t) { // Stop waiting if (t->wait_type != WAITTYPE_NONE) { t->wait_type = WAITTYPE_NONE; } - __KernelChangeThreadState(t, THREADSTATUS_READY); + __ChangeThreadState(t, THREADSTATUS_READY); +} + +/// Switches CPU context to that of the specified thread +void __SwitchContext(Thread* t, const char* reason) { + Thread* cur = __GetCurrentThread(); + + // Save context for current thread + if (cur) { + __SaveContext(cur->context); + + if (cur->IsRunning()) { + __ChangeReadyState(cur, true); + } + } + // Load context of new thread + if (t) { + __SetCurrentThread(t); + __ChangeReadyState(t, false); + t->status = (t->status | THREADSTATUS_RUNNING) & ~THREADSTATUS_READY; + t->wait_type = WAITTYPE_NONE; + __LoadContext(t->context); + } else { + __SetCurrentThread(NULL); + } +} + +/// Gets the next thread that is ready to be run by priority +Thread* __NextThread() { + Handle next; + Thread* cur = __GetCurrentThread(); + + if (cur && cur->IsRunning()) { + next = g_thread_ready_queue.pop_first_better(cur->current_priority); + } else { + next = g_thread_ready_queue.pop_first(); + } + if (next < 0) { + return NULL; + } + return Kernel::g_object_pool.GetFast<Thread>(next); +} + +/// Resumes a thread from waiting by marking it as "ready" +void __ResumeThreadFromWait(Handle handle) { + u32 error; + Thread* t = Kernel::g_object_pool.Get<Thread>(handle, error); + if (t) { + t->status &= ~THREADSTATUS_WAIT; + if (!(t->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { + __ChangeReadyState(t, true); + } + } +} + +/// Puts a thread in the wait state for the given type/reason +void __WaitCurThread(WaitType wait_type, const char* reason) { + Thread* t = __GetCurrentThread(); + t->wait_type = wait_type; + __ChangeThreadState(t, ThreadStatus(THREADSTATUS_WAIT | (t->status & THREADSTATUS_SUSPEND))); } /// Creates a new thread -Thread* __KernelCreateThread(Handle& handle, const char* name, u32 entry_point, s32 priority, +Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 priority, s32 processor_id, u32 stack_top, int stack_size) { Thread* t = new Thread; @@ -187,31 +245,31 @@ Thread* __KernelCreateThread(Handle& handle, const char* name, u32 entry_point, } /// Creates a new thread - wrapper for external user -Handle __KernelCreateThread(const char* name, u32 entry_point, s32 priority, s32 processor_id, +Handle CreateThread(const char* name, u32 entry_point, s32 priority, s32 processor_id, u32 stack_top, int stack_size) { if (name == NULL) { - ERROR_LOG(KERNEL, "__KernelCreateThread(): NULL name"); + ERROR_LOG(KERNEL, "CreateThread(): NULL name"); return -1; } if ((u32)stack_size < 0x200) { - ERROR_LOG(KERNEL, "__KernelCreateThread(name=%s): invalid stack_size=0x%08X", name, + ERROR_LOG(KERNEL, "CreateThread(name=%s): invalid stack_size=0x%08X", name, stack_size); return -1; } if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) { s32 new_priority = CLAMP(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); - WARN_LOG(KERNEL, "__KernelCreateThread(name=%s): invalid priority=0x%08X, clamping to %08X", + WARN_LOG(KERNEL, "CreateThread(name=%s): invalid priority=0x%08X, clamping to %08X", name, priority, new_priority); // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm // validity of this priority = new_priority; } if (!Memory::GetPointer(entry_point)) { - ERROR_LOG(KERNEL, "__KernelCreateThread(name=%s): invalid entry %08x", name, entry_point); + ERROR_LOG(KERNEL, "CreateThread(name=%s): invalid entry %08x", name, entry_point); return -1; } Handle handle; - Thread* t = __KernelCreateThread(handle, name, entry_point, priority, processor_id, stack_top, + Thread* t = CreateThread(handle, name, entry_point, priority, processor_id, stack_top, stack_size); HLE::EatCycles(32000); @@ -220,114 +278,62 @@ Handle __KernelCreateThread(const char* name, u32 entry_point, s32 priority, s32 // Technically, this should not eat all at once, and reschedule in the middle, but that's hard. HLE::ReSchedule("thread created"); - __KernelCallThread(t); + __CallThread(t); return handle; } -/// Switches CPU context to that of the specified thread -void __KernelSwitchContext(Thread* t, const char* reason) { - Thread* cur = __GetCurrentThread(); - - // Save context for current thread - if (cur) { - __KernelSaveContext(cur->context); - - if (cur->IsRunning()) { - __KernelChangeReadyState(cur, true); - } - } - // Load context of new thread - if (t) { - __SetCurrentThread(t); - __KernelChangeReadyState(t, false); - t->status = (t->status | THREADSTATUS_RUNNING) & ~THREADSTATUS_READY; - t->wait_type = WAITTYPE_NONE; - __KernelLoadContext(t->context); - } else { - __SetCurrentThread(NULL); - } -} - -/// Gets the next thread that is ready to be run by priority -Thread* __KernelNextThread() { - Handle next; - Thread* cur = __GetCurrentThread(); - - if (cur && cur->IsRunning()) { - next = g_thread_ready_queue.pop_first_better(cur->current_priority); - } else { - next = g_thread_ready_queue.pop_first(); - } - if (next < 0) { - return NULL; - } - return Kernel::g_object_pool.GetFast<Thread>(next); +/// Gets the current thread +Handle GetCurrentThread() { + return __GetCurrentThread()->GetHandle(); } /// Sets up the primary application thread -Handle __KernelSetupMainThread(s32 priority, int stack_size) { +Handle SetupMainThread(s32 priority, int stack_size) { Handle handle; // Initialize new "main" thread - Thread* t = __KernelCreateThread(handle, "main", Core::g_app_core->GetPC(), priority, + Thread* t = CreateThread(handle, "main", Core::g_app_core->GetPC(), priority, THREADPROCESSORID_0, Memory::SCRATCHPAD_VADDR_END, stack_size); - __KernelResetThread(t, 0); + __ResetThread(t, 0); // If running another thread already, set it to "ready" state Thread* cur = __GetCurrentThread(); if (cur && cur->IsRunning()) { - __KernelChangeReadyState(cur, true); + __ChangeReadyState(cur, true); } // Run new "main" thread __SetCurrentThread(t); t->status = THREADSTATUS_RUNNING; - __KernelLoadContext(t->context); + __LoadContext(t->context); return handle; } -/// Resumes a thread from waiting by marking it as "ready" -void __KernelResumeThreadFromWait(Handle handle) { - u32 error; - Thread* t = Kernel::g_object_pool.Get<Thread>(handle, error); - if (t) { - t->status &= ~THREADSTATUS_WAIT; - if (!(t->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { - __KernelChangeReadyState(t, true); - } - } -} - -/// Puts a thread in the wait state for the given type/reason -void __KernelWaitCurThread(WaitType wait_type, const char* reason) { - Thread* t = __GetCurrentThread(); - t->wait_type = wait_type; - __KernelChangeThreadState(t, ThreadStatus(THREADSTATUS_WAIT | (t->status & THREADSTATUS_SUSPEND))); -} - /// Reschedules to the next available thread (call after current thread is suspended) -void __KernelReschedule(const char* reason) { - Thread* next = __KernelNextThread(); +void Reschedule(const char* reason) { + Thread* next = __NextThread(); if (next > 0) { - __KernelSwitchContext(next, reason); + __SwitchContext(next, reason); } } //////////////////////////////////////////////////////////////////////////////////////////////////// /// Put current thread in a wait state - on WaitSynchronization -void __KernelWaitThread_Synchronization() { +void WaitThread_Synchronization() { // TODO(bunnei): Just a placeholder function for now... FixMe - __KernelWaitCurThread(WAITTYPE_SYNCH, "waitSynchronization called"); + __WaitCurThread(WAITTYPE_SYNCH, "waitSynchronization called"); } //////////////////////////////////////////////////////////////////////////////////////////////////// -void __KernelThreadingInit() { +void ThreadingInit() { } -void __KernelThreadingShutdown() { +void ThreadingShutdown() { } + +} // namespace diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 72e9a416d..2c0199273 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -7,8 +7,6 @@ #include "common/common_types.h" #include "core/hle/kernel/kernel.h" -class Thread; - enum ThreadPriority { THREADPRIO_HIGHEST = 0, THREADPRIO_DEFAULT = 16, @@ -21,18 +19,28 @@ enum ThreadProcessorId { THREADPROCESSORID_ALL = 0xFFFFFFFC, }; +namespace Kernel { + /// Creates a new thread - wrapper for external user -Handle __KernelCreateThread(const char* name, u32 entry_point, s32 priority, - s32 processor_id, u32 stack_top, int stack_size=Kernel::DEFAULT_STACK_SIZE); +Handle CreateThread(const char* name, u32 entry_point, s32 priority, s32 processor_id, + u32 stack_top, int stack_size=Kernel::DEFAULT_STACK_SIZE); /// Sets up the primary application thread -Handle __KernelSetupMainThread(s32 priority, int stack_size=Kernel::DEFAULT_STACK_SIZE); +Handle SetupMainThread(s32 priority, int stack_size=Kernel::DEFAULT_STACK_SIZE); /// Reschedules to the next available thread (call after current thread is suspended) -void __KernelReschedule(const char* reason); +void Reschedule(const char* reason); -void __KernelThreadingInit(); -void __KernelThreadingShutdown(); +/// Gets the current thread +Handle GetCurrentThread(); /// Put current thread in a wait state - on WaitSynchronization -void __KernelWaitThread_Synchronization(); +void WaitThread_Synchronization(); + +/// Initialize threading +void ThreadingInit(); + +/// Shutdown threading +void ThreadingShutdown(); + +} // namespace diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index a9141699c..6f0f099c6 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -123,7 +123,7 @@ Result WaitSynchronizationN(void* _out, void* _handles, u32 handle_count, u32 wa for (u32 i = 0; i < handle_count; i++) { DEBUG_LOG(SVC, "\thandle[%d]=0x%08X", i, handles[i]); } - __KernelReschedule("WaitSynchronizationN"); + Kernel::Reschedule("WaitSynchronizationN"); return 0; } @@ -175,7 +175,7 @@ Result CreateThread(void* thread, u32 priority, u32 entry_point, u32 arg, u32 st "threadpriority=0x%08X, processorid=0x%08X", entry_point, name.c_str(), arg, stack_top, priority, processor_id); - Handle handle = __KernelCreateThread(name.c_str(), entry_point, priority, processor_id, + Handle handle = Kernel::CreateThread(name.c_str(), entry_point, priority, processor_id, stack_top); Core::g_app_core->SetReg(1, 0xFEEDDEAF); |