diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index f2094f7a7..c84fdf91d 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -294,6 +294,51 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s3
     return handle;
 }
 
+/// Get the priority of the thread specified by handle
+u32 GetThreadPriority(const Handle handle) {
+    Thread* thread = g_object_pool.GetFast<Thread>(handle);
+    _assert_msg_(KERNEL, thread, "called, but thread is NULL!");
+    return thread->current_priority;
+}
+
+/// Set the priority of the thread specified by handle
+Result SetThreadPriority(Handle handle, s32 priority) {
+    Thread* thread = NULL;
+    if (!handle) {
+        thread = GetCurrentThread(); // TODO(bunnei): Is this correct behavior?
+    } else {
+        thread = g_object_pool.GetFast<Thread>(handle);
+    }
+    _assert_msg_(KERNEL, thread, "called, but thread is NULL!");
+
+    // If priority is invalid, clamp to valid range
+    if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) {
+        s32 new_priority = CLAMP(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST);
+        WARN_LOG(KERNEL, "invalid priority=0x%08X, clamping to %08X", priority, new_priority);
+        // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm
+        // validity of this
+        priority = new_priority;
+    }
+
+    // Change thread priority
+    s32 old = thread->current_priority;
+    g_thread_ready_queue.remove(old, handle);
+    thread->current_priority = priority;
+    g_thread_ready_queue.prepare(thread->current_priority);
+
+    // Change thread status to "ready" and push to ready queue
+    if (thread->IsRunning()) {
+        thread->status = (thread->status & ~THREADSTATUS_RUNNING) | THREADSTATUS_READY;
+    }
+    if (thread->IsReady()) {
+        g_thread_ready_queue.push_back(thread->current_priority, handle);
+    }
+
+    HLE::EatCycles(450);
+
+    return 0;
+}
+
 /// Sets up the primary application thread
 Handle SetupMainThread(s32 priority, int stack_size) {
     Handle handle;
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 9628f165d..094c8d43e 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -65,6 +65,12 @@ Handle GetCurrentThreadHandle();
 /// Put current thread in a wait state - on WaitSynchronization
 void WaitThread_Synchronization();
 
+/// Get the priority of the thread specified by handle
+u32 GetThreadPriority(const Handle handle);
+
+/// Set the priority of the thread specified by handle
+Result SetThreadPriority(Handle handle, s32 priority);
+
 /// Initialize threading
 void ThreadingInit();
 
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 0c2412a65..2384b7936 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -258,6 +258,18 @@ Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 p
     return 0;
 }
 
+/// Gets the priority for the specified thread
+Result GetThreadPriority(void* _priority, Handle handle) {
+    s32* priority = (s32*)_priority;
+    *priority = Kernel::GetThreadPriority(handle);
+    return 0;
+}
+
+/// Sets the priority for the specified thread
+Result SetThreadPriority(Handle handle, s32 priority) {
+    return Kernel::SetThreadPriority(handle, priority);
+}
+
 /// Create a mutex
 Result CreateMutex(void* _mutex, u32 initial_locked) {
     Handle* mutex = (Handle*)_mutex;
@@ -299,7 +311,18 @@ Result CreateEvent(void* _event, u32 reset_type) {
 /// Duplicates a kernel handle
 Result DuplicateHandle(void* _out, Handle handle) {
     Handle* out = (Handle*)_out;
-    ERROR_LOG(SVC, "(UNIMPLEMENTED) called handle=0x%08X", handle);
+    ERROR_LOG(SVC, "called handle=0x%08X", handle);
+
+    // Translate kernel handles -> real handles
+    if (handle == Kernel::CurrentThread) {
+        handle = Kernel::GetCurrentThreadHandle();
+    }
+    _assert_msg_(KERNEL, (handle != Kernel::CurrentProcess),
+        "(UNIMPLEMENTED) process handle duplication!");
+    
+    // TODO(bunnei): FixMe - This is a hack to return the handle that we were asked to duplicate.
+    *out = handle;
+
     return 0;
 }
 
@@ -327,8 +350,8 @@ const HLE::FunctionDef SVC_Table[] = {
     {0x08,  WrapI_UUUUU<CreateThread>,                  "CreateThread"},
     {0x09,  NULL,                                       "ExitThread"},
     {0x0A,  WrapV_S64<SleepThread>,                     "SleepThread"},
-    {0x0B,  NULL,                                       "GetThreadPriority"},
-    {0x0C,  NULL,                                       "SetThreadPriority"},
+    {0x0B,  WrapI_VU<GetThreadPriority>,                "GetThreadPriority"},
+    {0x0C,  WrapI_UI<SetThreadPriority>,                "SetThreadPriority"},
     {0x0D,  NULL,                                       "GetThreadAffinityMask"},
     {0x0E,  NULL,                                       "SetThreadAffinityMask"},
     {0x0F,  NULL,                                       "GetThreadIdealProcessor"},