summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2014-05-09 22:11:18 -0400
committerGravatar bunnei2014-05-09 22:11:18 -0400
commit6b264518a50ce21cb1be55ff3eac4e1c85582cfe (patch)
tree036ae3be74768165fbb4ee24db4cdba4ffadec2e /src
parentadded kernel logger to common (diff)
downloadyuzu-6b264518a50ce21cb1be55ff3eac4e1c85582cfe.tar.gz
yuzu-6b264518a50ce21cb1be55ff3eac4e1c85582cfe.tar.xz
yuzu-6b264518a50ce21cb1be55ff3eac4e1c85582cfe.zip
added initial kernel/thread modules
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/core.vcxproj4
-rw-r--r--src/core/core.vcxproj.filters15
-rw-r--r--src/core/hle/kernel/kernel.cpp142
-rw-r--r--src/core/hle/kernel/kernel.h121
-rw-r--r--src/core/hle/kernel/thread.cpp228
-rw-r--r--src/core/hle/kernel/thread.h36
7 files changed, 548 insertions, 0 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index eb4fef381..3fa5f51f1 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -22,6 +22,8 @@ set(SRCS core.cpp
22 hle/config_mem.cpp 22 hle/config_mem.cpp
23 hle/coprocessor.cpp 23 hle/coprocessor.cpp
24 hle/syscall.cpp 24 hle/syscall.cpp
25 hle/kernel/kernel.cpp
26 hle/kernel/thread.cpp
25 hle/service/apt.cpp 27 hle/service/apt.cpp
26 hle/service/gsp.cpp 28 hle/service/gsp.cpp
27 hle/service/hid.cpp 29 hle/service/hid.cpp
diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj
index b56661e48..59fc6f4fc 100644
--- a/src/core/core.vcxproj
+++ b/src/core/core.vcxproj
@@ -156,6 +156,8 @@
156 <ClCompile Include="hle\config_mem.cpp" /> 156 <ClCompile Include="hle\config_mem.cpp" />
157 <ClCompile Include="hle\coprocessor.cpp" /> 157 <ClCompile Include="hle\coprocessor.cpp" />
158 <ClCompile Include="hle\hle.cpp" /> 158 <ClCompile Include="hle\hle.cpp" />
159 <ClCompile Include="hle\kernel\kernel.cpp" />
160 <ClCompile Include="hle\kernel\thread.cpp" />
159 <ClCompile Include="hle\service\apt.cpp" /> 161 <ClCompile Include="hle\service\apt.cpp" />
160 <ClCompile Include="hle\service\gsp.cpp" /> 162 <ClCompile Include="hle\service\gsp.cpp" />
161 <ClCompile Include="hle\service\hid.cpp" /> 163 <ClCompile Include="hle\service\hid.cpp" />
@@ -198,6 +200,8 @@
198 <ClInclude Include="hle\coprocessor.h" /> 200 <ClInclude Include="hle\coprocessor.h" />
199 <ClInclude Include="hle\function_wrappers.h" /> 201 <ClInclude Include="hle\function_wrappers.h" />
200 <ClInclude Include="hle\hle.h" /> 202 <ClInclude Include="hle\hle.h" />
203 <ClInclude Include="hle\kernel\kernel.h" />
204 <ClInclude Include="hle\kernel\thread.h" />
201 <ClInclude Include="hle\service\apt.h" /> 205 <ClInclude Include="hle\service\apt.h" />
202 <ClInclude Include="hle\service\gsp.h" /> 206 <ClInclude Include="hle\service\gsp.h" />
203 <ClInclude Include="hle\service\hid.h" /> 207 <ClInclude Include="hle\service\hid.h" />
diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters
index 5c947ec23..ff988c116 100644
--- a/src/core/core.vcxproj.filters
+++ b/src/core/core.vcxproj.filters
@@ -28,6 +28,9 @@
28 <Filter Include="hle\service"> 28 <Filter Include="hle\service">
29 <UniqueIdentifier>{812c5189-ca49-4704-b842-3ffad09092d3}</UniqueIdentifier> 29 <UniqueIdentifier>{812c5189-ca49-4704-b842-3ffad09092d3}</UniqueIdentifier>
30 </Filter> 30 </Filter>
31 <Filter Include="hle\kernel">
32 <UniqueIdentifier>{f2b132eb-caff-4b04-aaae-88d24393a711}</UniqueIdentifier>
33 </Filter>
31 </ItemGroup> 34 </ItemGroup>
32 <ItemGroup> 35 <ItemGroup>
33 <ClCompile Include="arm\disassembler\arm_disasm.cpp"> 36 <ClCompile Include="arm\disassembler\arm_disasm.cpp">
@@ -114,6 +117,12 @@
114 <ClCompile Include="hle\config_mem.cpp"> 117 <ClCompile Include="hle\config_mem.cpp">
115 <Filter>hle</Filter> 118 <Filter>hle</Filter>
116 </ClCompile> 119 </ClCompile>
120 <ClCompile Include="hle\kernel\thread.cpp">
121 <Filter>hle\kernel</Filter>
122 </ClCompile>
123 <ClCompile Include="hle\kernel\kernel.cpp">
124 <Filter>hle\kernel</Filter>
125 </ClCompile>
117 </ItemGroup> 126 </ItemGroup>
118 <ItemGroup> 127 <ItemGroup>
119 <ClInclude Include="arm\disassembler\arm_disasm.h"> 128 <ClInclude Include="arm\disassembler\arm_disasm.h">
@@ -223,6 +232,12 @@
223 <ClInclude Include="hle\config_mem.h"> 232 <ClInclude Include="hle\config_mem.h">
224 <Filter>hle</Filter> 233 <Filter>hle</Filter>
225 </ClInclude> 234 </ClInclude>
235 <ClInclude Include="hle\kernel\thread.h">
236 <Filter>hle\kernel</Filter>
237 </ClInclude>
238 <ClInclude Include="hle\kernel\kernel.h">
239 <Filter>hle\kernel</Filter>
240 </ClInclude>
226 </ItemGroup> 241 </ItemGroup>
227 <ItemGroup> 242 <ItemGroup>
228 <Text Include="CMakeLists.txt" /> 243 <Text Include="CMakeLists.txt" />
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
new file mode 100644
index 000000000..fc494fe30
--- /dev/null
+++ b/src/core/hle/kernel/kernel.cpp
@@ -0,0 +1,142 @@
1// Copyright 2014 Citra Emulator Project / PPSSPP Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <string.h>
8
9#include "common/common.h"
10
11#include "core/hle/kernel/kernel.h"
12#include "core/hle/kernel/thread.h"
13
14KernelObjectPool g_kernel_objects;
15
16void __KernelInit() {
17 __KernelThreadingInit();
18}
19
20void __KernelShutdown() {
21 __KernelThreadingShutdown();
22}
23
24KernelObjectPool::KernelObjectPool() {
25 memset(occupied, 0, sizeof(bool) * MAX_COUNT);
26 next_id = INITIAL_NEXT_ID;
27}
28
29UID KernelObjectPool::Create(KernelObject *obj, int range_bottom, int range_top) {
30 if (range_top > MAX_COUNT) {
31 range_top = MAX_COUNT;
32 }
33 if (next_id >= range_bottom && next_id < range_top) {
34 range_bottom = next_id++;
35 }
36 for (int i = range_bottom; i < range_top; i++) {
37 if (!occupied[i]) {
38 occupied[i] = true;
39 pool[i] = obj;
40 pool[i]->uid = i + HANDLE_OFFSET;
41 return i + HANDLE_OFFSET;
42 }
43 }
44 ERROR_LOG(HLE, "Unable to allocate kernel object, too many objects slots in use.");
45 return 0;
46}
47
48bool KernelObjectPool::IsValid(UID handle)
49{
50 int index = handle - HANDLE_OFFSET;
51 if (index < 0)
52 return false;
53 if (index >= MAX_COUNT)
54 return false;
55
56 return occupied[index];
57}
58
59void KernelObjectPool::Clear()
60{
61 for (int i = 0; i < MAX_COUNT; i++)
62 {
63 //brutally clear everything, no validation
64 if (occupied[i])
65 delete pool[i];
66 occupied[i] = false;
67 }
68 memset(pool, 0, sizeof(KernelObject*)*MAX_COUNT);
69 next_id = INITIAL_NEXT_ID;
70}
71
72KernelObject *&KernelObjectPool::operator [](UID handle)
73{
74 _dbg_assert_msg_(KERNEL, IsValid(handle), "GRABBING UNALLOCED KERNEL OBJ");
75 return pool[handle - HANDLE_OFFSET];
76}
77
78void KernelObjectPool::List() {
79 for (int i = 0; i < MAX_COUNT; i++) {
80 if (occupied[i]) {
81 if (pool[i]) {
82 INFO_LOG(KERNEL, "KO %i: %s \"%s\"", i + HANDLE_OFFSET, pool[i]->GetTypeName(),
83 pool[i]->GetName());
84 }
85 }
86 }
87}
88
89int KernelObjectPool::GetCount()
90{
91 int count = 0;
92 for (int i = 0; i < MAX_COUNT; i++)
93 {
94 if (occupied[i])
95 count++;
96 }
97 return count;
98}
99
100KernelObject *KernelObjectPool::CreateByIDType(int type) {
101 // Used for save states. This is ugly, but what other way is there?
102 switch (type) {
103 //case SCE_KERNEL_TMID_Alarm:
104 // return __KernelAlarmObject();
105 //case SCE_KERNEL_TMID_EventFlag:
106 // return __KernelEventFlagObject();
107 //case SCE_KERNEL_TMID_Mbox:
108 // return __KernelMbxObject();
109 //case SCE_KERNEL_TMID_Fpl:
110 // return __KernelMemoryFPLObject();
111 //case SCE_KERNEL_TMID_Vpl:
112 // return __KernelMemoryVPLObject();
113 //case PPSSPP_KERNEL_TMID_PMB:
114 // return __KernelMemoryPMBObject();
115 //case PPSSPP_KERNEL_TMID_Module:
116 // return __KernelModuleObject();
117 //case SCE_KERNEL_TMID_Mpipe:
118 // return __KernelMsgPipeObject();
119 //case SCE_KERNEL_TMID_Mutex:
120 // return __KernelMutexObject();
121 //case SCE_KERNEL_TMID_LwMutex:
122 // return __KernelLwMutexObject();
123 //case SCE_KERNEL_TMID_Semaphore:
124 // return __KernelSemaphoreObject();
125 //case SCE_KERNEL_TMID_Callback:
126 // return __KernelCallbackObject();
127 //case SCE_KERNEL_TMID_Thread:
128 // return __KernelThreadObject();
129 //case SCE_KERNEL_TMID_VTimer:
130 // return __KernelVTimerObject();
131 //case SCE_KERNEL_TMID_Tlspl:
132 // return __KernelTlsplObject();
133 //case PPSSPP_KERNEL_TMID_File:
134 // return __KernelFileNodeObject();
135 //case PPSSPP_KERNEL_TMID_DirList:
136 // return __KernelDirListingObject();
137
138 default:
139 ERROR_LOG(COMMON, "Unable to load state: could not find object type %d.", type);
140 return NULL;
141 }
142}
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
new file mode 100644
index 000000000..2381ca7f7
--- /dev/null
+++ b/src/core/hle/kernel/kernel.h
@@ -0,0 +1,121 @@
1// Copyright 2014 Citra Emulator Project / PPSSPP Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/common_types.h"
8
9typedef u32 UID;
10
11class KernelObjectPool;
12
13class KernelObject {
14 friend class KernelObjectPool;
15 u32 uid;
16public:
17 virtual ~KernelObject() {}
18 UID GetUID() const { return uid; }
19 virtual const char *GetTypeName() { return "[BAD KERNEL OBJECT TYPE]"; }
20 virtual const char *GetName() { return "[UNKNOWN KERNEL OBJECT]"; }
21 virtual int GetIDType() const = 0;
22 //virtual void GetQuickInfo(char *ptr, int size);
23};
24
25class KernelObjectPool {
26public:
27 KernelObjectPool();
28 ~KernelObjectPool() {}
29
30 // Allocates a UID within the range and inserts the object into the map.
31 UID Create(KernelObject *obj, int range_bottom=INITIAL_NEXT_ID, int range_top=0x7FFFFFFF);
32
33 static KernelObject *CreateByIDType(int type);
34
35 template <class T>
36 u32 Destroy(UID handle) {
37 u32 error;
38 if (Get<T>(handle, error)) {
39 occupied[handle - handleOffset] = false;
40 delete pool[handle - handleOffset];
41 }
42 return error;
43 };
44
45 bool IsValid(UID handle);
46
47 template <class T>
48 T* Get(UID handle, u32& outError) {
49 if (handle < handleOffset || handle >= handleOffset + maxCount || !occupied[handle - handleOffset]) {
50 // Tekken 6 spams 0x80020001 gets wrong with no ill effects, also on the real PSP
51 if (handle != 0 && (u32)handle != 0x80020001) {
52 WARN_LOG(SCEKERNEL, "Kernel: Bad object handle %i (%08x)", handle, handle);
53 }
54 outError = T::GetMissingErrorCode();
55 return 0;
56 } else {
57 // Previously we had a dynamic_cast here, but since RTTI was disabled traditionally,
58 // it just acted as a static case and everything worked. This means that we will never
59 // see the Wrong type object error below, but we'll just have to live with that danger.
60 T* t = static_cast<T*>(pool[handle - handleOffset]);
61 if (t == 0 || t->GetIDType() != T::GetStaticIDType()) {
62 WARN_LOG(SCEKERNEL, "Kernel: Wrong object type for %i (%08x)", handle, handle);
63 outError = T::GetMissingErrorCode();
64 return 0;
65 }
66 outError = SCE_KERNEL_ERROR_OK;
67 return t;
68 }
69 }
70
71 // ONLY use this when you know the handle is valid.
72 template <class T>
73 T *GetFast(UID handle) {
74 const UID realHandle = handle - handleOffset;
75 _dbg_assert_(SCEKERNEL, realHandle >= 0 && realHandle < maxCount && occupied[realHandle]);
76 return static_cast<T *>(pool[realHandle]);
77 }
78
79 template <class T, typename ArgT>
80 void Iterate(bool func(T *, ArgT), ArgT arg) {
81 int type = T::GetStaticIDType();
82 for (int i = 0; i < maxCount; i++)
83 {
84 if (!occupied[i])
85 continue;
86 T *t = static_cast<T *>(pool[i]);
87 if (t->GetIDType() == type) {
88 if (!func(t, arg))
89 break;
90 }
91 }
92 }
93
94 bool GetIDType(UID handle, int *type) const {
95 if ((handle < HANDLE_OFFSET) || (handle >= HANDLE_OFFSET + MAX_COUNT) ||
96 !occupied[handle - HANDLE_OFFSET]) {
97 ERROR_LOG(KERNEL, "Kernel: Bad object handle %i (%08x)", handle, handle);
98 return false;
99 }
100 KernelObject *t = pool[handle - HANDLE_OFFSET];
101 *type = t->GetIDType();
102 return true;
103 }
104
105 KernelObject *&operator [](UID handle);
106 void List();
107 void Clear();
108 int GetCount();
109
110private:
111 enum {
112 MAX_COUNT = 0x1000,
113 HANDLE_OFFSET = 0x100,
114 INITIAL_NEXT_ID = 0x10,
115 };
116 KernelObject *pool[MAX_COUNT];
117 bool occupied[MAX_COUNT];
118 int next_id;
119};
120
121extern KernelObjectPool g_kernel_objects;
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
new file mode 100644
index 000000000..0ed35de83
--- /dev/null
+++ b/src/core/hle/kernel/thread.cpp
@@ -0,0 +1,228 @@
1// Copyright 2014 Citra Emulator Project / PPSSPP Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include <stdio.h>
6
7#include <list>
8#include <vector>
9#include <map>
10#include <string>
11
12#include "common/common.h"
13
14#include "core/hle/kernel/kernel.h"
15#include "core/hle/kernel/thread.h"
16
17// Real CTR struct, don't change the fields.
18struct NativeThread {
19 //u32 Pointer to vtable
20 //u32 Reference count
21 //KProcess* Process the thread belongs to (virtual address)
22 //u32 Thread id
23 //u32* ptr = *(KThread+0x8C) - 0xB0
24 //u32* End-address of the page for this thread allocated in the 0xFF4XX000 region. Thus,
25 // if the beginning of this mapped page is 0xFF401000, this ptr would be 0xFF402000.
26 //KThread* Previous ? (virtual address)
27 //KThread* Next ? (virtual address)
28};
29
30struct ThreadWaitInfo {
31 u32 wait_value;
32 u32 timeout_ptr;
33};
34
35class Thread : public KernelObject {
36public:
37 /*const char *GetName() { return nt.name; }*/
38 const char *GetTypeName() { return "Thread"; }
39 //void GetQuickInfo(char *ptr, int size)
40 //{
41 // sprintf(ptr, "pc= %08x sp= %08x %s %s %s %s %s %s (wt=%i wid=%i wv= %08x )",
42 // context.pc, context.r[13], // 13 is stack pointer
43 // (nt.status & THREADSTATUS_RUNNING) ? "RUN" : "",
44 // (nt.status & THREADSTATUS_READY) ? "READY" : "",
45 // (nt.status & THREADSTATUS_WAIT) ? "WAIT" : "",
46 // (nt.status & THREADSTATUS_SUSPEND) ? "SUSPEND" : "",
47 // (nt.status & THREADSTATUS_DORMANT) ? "DORMANT" : "",
48 // (nt.status & THREADSTATUS_DEAD) ? "DEAD" : "",
49 // nt.waitType,
50 // nt.waitID,
51 // waitInfo.waitValue);
52 //}
53
54 //static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_THID; }
55 //static int GetStaticIDType() { return SCE_KERNEL_TMID_Thread; }
56 //int GetIDType() const { return SCE_KERNEL_TMID_Thread; }
57
58 //bool AllocateStack(u32 &stack_size) {
59 // FreeStack();
60
61 // bool fromTop = (nt.attr & PSP_THREAD_ATTR_LOW_STACK) == 0;
62 // if (nt.attr & PSP_THREAD_ATTR_KERNEL)
63 // {
64 // // Allocate stacks for kernel threads (idle) in kernel RAM
65 // currentStack.start = kernelMemory.Alloc(stack_size, fromTop, (std::string("stack/") + nt.name).c_str());
66 // }
67 // else
68 // {
69 // currentStack.start = userMemory.Alloc(stack_size, fromTop, (std::string("stack/") + nt.name).c_str());
70 // }
71 // if (currentStack.start == (u32)-1)
72 // {
73 // currentStack.start = 0;
74 // nt.initialStack = 0;
75 // ERROR_LOG(KERNEL, "Failed to allocate stack for thread");
76 // return false;
77 // }
78
79 // nt.initialStack = currentStack.start;
80 // nt.stack_size = stack_size;
81 // return true;
82 //}
83
84 //bool FillStack() {
85 // // Fill the stack.
86 // if ((nt.attr & PSP_THREAD_ATTR_NO_FILLSTACK) == 0) {
87 // Memory::Memset(currentStack.start, 0xFF, nt.stack_size);
88 // }
89 // context.r[MIPS_REG_SP] = currentStack.start + nt.stack_size;
90 // currentStack.end = context.r[MIPS_REG_SP];
91 // // The k0 section is 256 bytes at the top of the stack.
92 // context.r[MIPS_REG_SP] -= 256;
93 // context.r[MIPS_REG_K0] = context.r[MIPS_REG_SP];
94 // u32 k0 = context.r[MIPS_REG_K0];
95 // Memory::Memset(k0, 0, 0x100);
96 // Memory::Write_U32(GetUID(), k0 + 0xc0);
97 // Memory::Write_U32(nt.initialStack, k0 + 0xc8);
98 // Memory::Write_U32(0xffffffff, k0 + 0xf8);
99 // Memory::Write_U32(0xffffffff, k0 + 0xfc);
100 // // After k0 comes the arguments, which is done by sceKernelStartThread().
101
102 // Memory::Write_U32(GetUID(), nt.initialStack);
103 // return true;
104 //}
105
106 //void FreeStack() {
107 // if (currentStack.start != 0) {
108 // DEBUG_LOG(KERNEL, "Freeing thread stack %s", nt.name);
109
110 // if ((nt.attr & PSP_THREAD_ATTR_CLEAR_STACK) != 0 && nt.initialStack != 0) {
111 // Memory::Memset(nt.initialStack, 0, nt.stack_size);
112 // }
113
114 // if (nt.attr & PSP_THREAD_ATTR_KERNEL) {
115 // kernelMemory.Free(currentStack.start);
116 // }
117 // else {
118 // userMemory.Free(currentStack.start);
119 // }
120 // currentStack.start = 0;
121 // }
122 //}
123
124 //bool PushExtendedStack(u32 size) {
125 // u32 stack = userMemory.Alloc(size, true, (std::string("extended/") + nt.name).c_str());
126 // if (stack == (u32)-1)
127 // return false;
128
129 // pushed_stacks.push_back(currentStack);
130 // currentStack.start = stack;
131 // currentStack.end = stack + size;
132 // nt.initialStack = currentStack.start;
133 // nt.stack_size = currentStack.end - currentStack.start;
134
135 // // We still drop the threadID at the bottom and fill it, but there's no k0.
136 // Memory::Memset(currentStack.start, 0xFF, nt.stack_size);
137 // Memory::Write_U32(GetUID(), nt.initialStack);
138 // return true;
139 //}
140
141 //bool PopExtendedStack() {
142 // if (pushed_stacks.size() == 0) {
143 // return false;
144 // }
145 // userMemory.Free(currentStack.start);
146 // currentStack = pushed_stacks.back();
147 // pushed_stacks.pop_back();
148 // nt.initialStack = currentStack.start;
149 // nt.stack_size = currentStack.end - currentStack.start;
150 // return true;
151 //}
152
153 Thread() {
154 currentStack.start = 0;
155 }
156
157 // Can't use a destructor since savestates will call that too.
158 //void Cleanup() {
159 // // Callbacks are automatically deleted when their owning thread is deleted.
160 // for (auto it = callbacks.begin(), end = callbacks.end(); it != end; ++it)
161 // kernelObjects.Destroy<Callback>(*it);
162
163 // if (pushed_stacks.size() != 0)
164 // {
165 // WARN_LOG(KERNEL, "Thread ended within an extended stack");
166 // for (size_t i = 0; i < pushed_stacks.size(); ++i)
167 // userMemory.Free(pushed_stacks[i].start);
168 // }
169 // FreeStack();
170 //}
171
172 void setReturnValue(u32 retval);
173 void setReturnValue(u64 retval);
174 void resumeFromWait();
175 //bool isWaitingFor(WaitType type, int id);
176 //int getWaitID(WaitType type);
177 ThreadWaitInfo getWaitInfo();
178
179 // Utils
180 //inline bool isRunning() const { return (nt.status & THREADSTATUS_RUNNING) != 0; }
181 //inline bool isStopped() const { return (nt.status & THREADSTATUS_DORMANT) != 0; }
182 //inline bool isReady() const { return (nt.status & THREADSTATUS_READY) != 0; }
183 //inline bool isWaiting() const { return (nt.status & THREADSTATUS_WAIT) != 0; }
184 //inline bool isSuspended() const { return (nt.status & THREADSTATUS_SUSPEND) != 0; }
185
186 NativeThread nt;
187
188 ThreadWaitInfo waitInfo;
189 UID moduleId;
190
191 bool isProcessingCallbacks;
192 u32 currentMipscallId;
193 UID currentCallbackId;
194
195 ThreadContext context;
196
197 std::vector<UID> callbacks;
198
199 std::list<u32> pending_calls;
200
201 struct StackInfo {
202 u32 start;
203 u32 end;
204 };
205 // This is a stack of... stacks, since sceKernelExtendThreadStack() can recurse.
206 // These are stacks that aren't "active" right now, but will pop off once the func returns.
207 std::vector<StackInfo> pushed_stacks;
208
209 StackInfo currentStack;
210
211 // For thread end.
212 std::vector<UID> waiting_threads;
213 // Key is the callback id it was for, or if no callback, the thread id.
214 std::map<UID, u64> paused_waits;
215};
216
217void __KernelThreadingInit() {
218}
219
220void __KernelThreadingShutdown() {
221}
222
223//const char *__KernelGetThreadName(UID threadID);
224//
225//void __KernelSaveContext(ThreadContext *ctx);
226//void __KernelLoadContext(ThreadContext *ctx);
227
228//void __KernelSwitchContext(Thread *target, const char *reason); \ No newline at end of file
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
new file mode 100644
index 000000000..c3cdca31f
--- /dev/null
+++ b/src/core/hle/kernel/thread.h
@@ -0,0 +1,36 @@
1// Copyright 2014 Citra Emulator Project / PPSSPP Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/common_types.h"
8
9enum ThreadStatus {
10 THREADSTATUS_RUNNING = 1,
11 THREADSTATUS_READY = 2,
12 THREADSTATUS_WAIT = 4,
13 THREADSTATUS_SUSPEND = 8,
14 THREADSTATUS_DORMANT = 16,
15 THREADSTATUS_DEAD = 32,
16
17 THREADSTATUS_WAITSUSPEND = THREADSTATUS_WAIT | THREADSTATUS_SUSPEND
18};
19
20struct ThreadContext {
21 void reset();
22
23 u32 reg[16];
24 u32 cpsr;
25 u32 pc;
26};
27
28void __KernelThreadingInit();
29void __KernelThreadingShutdown();
30
31//const char *__KernelGetThreadName(SceUID threadID);
32//
33//void __KernelSaveContext(ThreadContext *ctx);
34//void __KernelLoadContext(ThreadContext *ctx);
35
36//void __KernelSwitchContext(Thread *target, const char *reason); \ No newline at end of file