From 14ae026386cf3f984d60401e2104165c3ca3266b Mon Sep 17 00:00:00 2001
From: bunnei <ericbunnie@gmail.com>
Date: Sat, 17 May 2014 00:56:00 -0400
Subject: [PATCH] - added enum ThreadProcessorId

- reorganized some kernel thread functions
- added placeholder __KernelWaitThread_Synchronization function
---
 src/core/hle/kernel/thread.cpp | 141 +++++++++++++++++++++------------
 src/core/hle/kernel/thread.h   |  19 ++++-
 2 files changed, 107 insertions(+), 53 deletions(-)

diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 76a73747d8..b967b3c624 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -21,20 +21,14 @@
 
 // Enums
 
-enum ThreadPriority {
-    THREADPRIO_HIGHEST = 0,
-    THREADPRIO_DEFAULT = 16,
-    THREADPRIO_LOWEST = 31,
-};
-
 enum ThreadStatus {
-    THREADSTATUS_RUNNING = 1,
-    THREADSTATUS_READY   = 2,
-    THREADSTATUS_WAIT    = 4,
-    THREADSTATUS_SUSPEND = 8,
-    THREADSTATUS_DORMANT = 16,
-    THREADSTATUS_DEAD    = 32,
-    THREADSTATUS_WAITSUSPEND = THREADSTATUS_WAIT | THREADSTATUS_SUSPEND
+    THREADSTATUS_RUNNING        = 1,
+    THREADSTATUS_READY          = 2,
+    THREADSTATUS_WAIT           = 4,
+    THREADSTATUS_SUSPEND        = 8,
+    THREADSTATUS_DORMANT        = 16,
+    THREADSTATUS_DEAD           = 32,
+    THREADSTATUS_WAITSUSPEND    = THREADSTATUS_WAIT | THREADSTATUS_SUSPEND
 };
 
 enum WaitType {
@@ -46,8 +40,6 @@ enum WaitType {
     WAITTYPE_VBLANK,
     WAITTYPE_MUTEX,
     WAITTYPE_SYNCH,
-    
-    NUM_WAITTYPES
 };
 
 typedef s32 Handle;
@@ -164,32 +156,6 @@ void __KernelResetThread(Thread *t, s32 lowest_priority) {
     t->wait_type = WAITTYPE_NONE;
 }
 
-/// Creates a new thread
-Thread *__KernelCreateThread(Handle &handle, const char *name, u32 entry_point, s32 priority, 
-    s32 processor_id, u32 stack_top, int stack_size) {
-    static u32 _handle_count = 1;
-    
-    Thread *t = new Thread;
-    
-    handle = (_handle_count++);
-    
-    g_thread_queue.push_back(handle);
-    g_thread_ready_queue.prepare(priority);
-    
-    t->status = THREADSTATUS_DORMANT;
-    t->entry_point = entry_point;
-    t->stack_top = stack_top;
-    t->stack_size = stack_size;
-    t->initial_priority = t->current_priority = priority;
-    t->processor_id = processor_id;
-    t->wait_type = WAITTYPE_NONE;
-    
-    strncpy(t->name, name, KERNEL_MAX_NAME_LENGTH);
-    t->name[KERNEL_MAX_NAME_LENGTH] = '\0';
-    
-    return t;
-}
-
 /// Change a thread to "ready" state
 void __KernelChangeReadyState(Thread *t, bool ready) {
     Handle handle = t->GetHandle();
@@ -222,6 +188,79 @@ 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) {
+    // Stop waiting
+    if (t->wait_type != WAITTYPE_NONE) {
+        t->wait_type = WAITTYPE_NONE;
+    }
+    __KernelChangeThreadState(t, THREADSTATUS_READY);
+}
+
+/// Creates a new thread
+Thread *__KernelCreateThread(Handle &handle, const char *name, u32 entry_point, s32 priority,
+    s32 processor_id, u32 stack_top, int stack_size) {
+
+    Thread *t = new Thread;
+    
+    handle = g_kernel_objects.Create(t);
+    
+    g_thread_queue.push_back(handle);
+    g_thread_ready_queue.prepare(priority);
+    
+    t->status = THREADSTATUS_DORMANT;
+    t->entry_point = entry_point;
+    t->stack_top = stack_top;
+    t->stack_size = stack_size;
+    t->initial_priority = t->current_priority = priority;
+    t->processor_id = processor_id;
+    t->wait_type = WAITTYPE_NONE;
+    
+    strncpy(t->name, name, KERNEL_MAX_NAME_LENGTH);
+    t->name[KERNEL_MAX_NAME_LENGTH] = '\0';
+    
+    return t;
+}
+
+/// 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) {
+    if (name == NULL) {
+        ERROR_LOG(KERNEL, "__KernelCreateThread(): NULL name");
+        return -1;
+    }
+    if ((u32)stack_size < 0x200) {
+        ERROR_LOG(KERNEL, "__KernelCreateThread(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",
+            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);
+        return -1;
+    }
+    Handle handle;
+    Thread *t = __KernelCreateThread(handle, name, entry_point, priority, processor_id, stack_top, 
+        stack_size);
+
+    HLE::EatCycles(32000);
+
+    // This won't schedule to the new thread, but it may to one woken from eating cycles.
+    // Technically, this should not eat all at once, and reschedule in the middle, but that's hard.
+    HLE::ReSchedule("thread created");
+
+    __KernelCallThread(t);
+    
+    return handle;
+}
+
 /// Switches CPU context to that of the specified thread
 void __KernelSwitchContext(Thread* t, const char *reason) {
     Thread *cur = __GetCurrentThread();
@@ -262,22 +301,13 @@ Thread *__KernelNextThread() {
     return g_kernel_objects.GetFast<Thread>(next);
 }
 
-/// Calls a thread by marking it as "ready" (note: will not actually execute until current thread yields)
-void __KernelCallThread(Thread *t) {
-    // Stop waiting
-    if (t->wait_type != WAITTYPE_NONE) {
-        t->wait_type = WAITTYPE_NONE;
-    }
-    __KernelChangeThreadState(t, THREADSTATUS_READY);
-}
-
 /// Sets up the primary application thread
 Handle __KernelSetupMainThread(s32 priority, int stack_size) {
     Handle handle;
     
     // Initialize new "main" thread
     Thread *t = __KernelCreateThread(handle, "main", Core::g_app_core->GetPC(), priority, 
-        0xFFFFFFFE, Memory::SCRATCHPAD_VADDR_END, stack_size);
+        THREADPROCESSORID_0, Memory::SCRATCHPAD_VADDR_END, stack_size);
     
     __KernelResetThread(t, 0);
     
@@ -322,6 +352,15 @@ void __KernelReschedule(const char *reason) {
     }
 }
 
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/// Wait thread - on WaitSynchronization
+void __KernelWaitThread_Synchronization() {
+    // TODO(bunnei): Just a placeholder function for now... FixMe
+    __KernelWaitCurThread(WAITTYPE_SYNCH, "waitSynchronization called");
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
 
 void __KernelThreadingInit() {
 }
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index add6107d76..8138be26f7 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -9,8 +9,20 @@
 
 class Thread;
 
-/// Creates a new thread
-Thread *__KernelCreateThread(Handle &handle, const char *name, u32 entry_point, s32 priority, 
+enum ThreadPriority {
+    THREADPRIO_HIGHEST      = 0,
+    THREADPRIO_DEFAULT      = 16,
+    THREADPRIO_LOWEST       = 31,
+};
+
+enum ThreadProcessorId {
+    THREADPROCESSORID_0     = 0xFFFFFFFE,
+    THREADPROCESSORID_1     = 0xFFFFFFFD,
+    THREADPROCESSORID_ALL   = 0xFFFFFFFC,
+};
+
+/// 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);
 
 /// Sets up the primary application thread
@@ -18,3 +30,6 @@ Handle __KernelSetupMainThread(s32 priority, int stack_size=KERNEL_DEFAULT_STACK
 
 void __KernelThreadingInit();
 void __KernelThreadingShutdown();
+
+/// Wait thread - on WaitSynchronization
+void __KernelWaitThread_Synchronization();
-- 
GitLab