summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/thread.cpp
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/core/hle/kernel/thread.cpp
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/core/hle/kernel/thread.cpp')
-rw-r--r--src/core/hle/kernel/thread.cpp228
1 files changed, 228 insertions, 0 deletions
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