summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/thread.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2015-01-10 15:19:21 -0500
committerGravatar bunnei2015-01-10 15:19:21 -0500
commit5a4b361f6065d33fd9efb73b3654910f74d5e3cd (patch)
treecb6506c96f7880ef38f783221d4dd5b34978e3ef /src/core/hle/kernel/thread.cpp
parentFix Windows build (diff)
parentKernel: Start using boost::intrusive_ptr for lifetime management (diff)
downloadyuzu-5a4b361f6065d33fd9efb73b3654910f74d5e3cd.tar.gz
yuzu-5a4b361f6065d33fd9efb73b3654910f74d5e3cd.tar.xz
yuzu-5a4b361f6065d33fd9efb73b3654910f74d5e3cd.zip
Merge pull request #455 from yuriks/handle-reform3
Kernel Lifetime Reform Pt. 3
Diffstat (limited to 'src/core/hle/kernel/thread.cpp')
-rw-r--r--src/core/hle/kernel/thread.cpp63
1 files changed, 30 insertions, 33 deletions
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 0ae1a21df..dd20ca30e 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -36,7 +36,7 @@ ResultVal<bool> Thread::WaitSynchronization() {
36} 36}
37 37
38// Lists all thread ids that aren't deleted/etc. 38// Lists all thread ids that aren't deleted/etc.
39static std::vector<Thread*> thread_list; // TODO(yuriks): Owned 39static std::vector<SharedPtr<Thread>> thread_list;
40 40
41// Lists only ready thread ids. 41// Lists only ready thread ids.
42static Common::ThreadQueueList<Thread*, THREADPRIO_LOWEST+1> thread_ready_queue; 42static Common::ThreadQueueList<Thread*, THREADPRIO_LOWEST+1> thread_ready_queue;
@@ -110,8 +110,8 @@ void Thread::Stop(const char* reason) {
110 110
111 ChangeReadyState(this, false); 111 ChangeReadyState(this, false);
112 status = THREADSTATUS_DORMANT; 112 status = THREADSTATUS_DORMANT;
113 for (Thread* waiting_thread : waiting_threads) { 113 for (auto& waiting_thread : waiting_threads) {
114 if (CheckWaitType(waiting_thread, WAITTYPE_THREADEND, this)) 114 if (CheckWaitType(waiting_thread.get(), WAITTYPE_THREADEND, this))
115 waiting_thread->ResumeFromWait(); 115 waiting_thread->ResumeFromWait();
116 } 116 }
117 waiting_threads.clear(); 117 waiting_threads.clear();
@@ -143,15 +143,15 @@ Thread* ArbitrateHighestPriorityThread(Object* arbiter, u32 address) {
143 s32 priority = THREADPRIO_LOWEST; 143 s32 priority = THREADPRIO_LOWEST;
144 144
145 // Iterate through threads, find highest priority thread that is waiting to be arbitrated... 145 // Iterate through threads, find highest priority thread that is waiting to be arbitrated...
146 for (Thread* thread : thread_list) { 146 for (auto& thread : thread_list) {
147 if (!CheckWaitType(thread, WAITTYPE_ARB, arbiter, address)) 147 if (!CheckWaitType(thread.get(), WAITTYPE_ARB, arbiter, address))
148 continue; 148 continue;
149 149
150 if (thread == nullptr) 150 if (thread == nullptr)
151 continue; // TODO(yuriks): Thread handle will hang around forever. Should clean up. 151 continue; // TODO(yuriks): Thread handle will hang around forever. Should clean up.
152 152
153 if(thread->current_priority <= priority) { 153 if(thread->current_priority <= priority) {
154 highest_priority_thread = thread; 154 highest_priority_thread = thread.get();
155 priority = thread->current_priority; 155 priority = thread->current_priority;
156 } 156 }
157 } 157 }
@@ -168,8 +168,8 @@ Thread* ArbitrateHighestPriorityThread(Object* arbiter, u32 address) {
168void ArbitrateAllThreads(Object* arbiter, u32 address) { 168void ArbitrateAllThreads(Object* arbiter, u32 address) {
169 169
170 // Iterate through threads, find highest priority thread that is waiting to be arbitrated... 170 // Iterate through threads, find highest priority thread that is waiting to be arbitrated...
171 for (Thread* thread : thread_list) { 171 for (auto& thread : thread_list) {
172 if (CheckWaitType(thread, WAITTYPE_ARB, arbiter, address)) 172 if (CheckWaitType(thread.get(), WAITTYPE_ARB, arbiter, address))
173 thread->ResumeFromWait(); 173 thread->ResumeFromWait();
174 } 174 }
175} 175}
@@ -241,7 +241,7 @@ static int ThreadWakeupEventType = -1;
241/// Callback that will wake up the thread it was scheduled for 241/// Callback that will wake up the thread it was scheduled for
242static void ThreadWakeupCallback(u64 parameter, int cycles_late) { 242static void ThreadWakeupCallback(u64 parameter, int cycles_late) {
243 Handle handle = static_cast<Handle>(parameter); 243 Handle handle = static_cast<Handle>(parameter);
244 Thread* thread = Kernel::g_handle_table.Get<Thread>(handle); 244 SharedPtr<Thread> thread = Kernel::g_handle_table.Get<Thread>(handle);
245 if (thread == nullptr) { 245 if (thread == nullptr) {
246 LOG_ERROR(Kernel, "Thread doesn't exist %u", handle); 246 LOG_ERROR(Kernel, "Thread doesn't exist %u", handle);
247 return; 247 return;
@@ -278,20 +278,18 @@ static void DebugThreadQueue() {
278 return; 278 return;
279 } 279 }
280 LOG_DEBUG(Kernel, "0x%02X 0x%08X (current)", thread->current_priority, GetCurrentThread()->GetHandle()); 280 LOG_DEBUG(Kernel, "0x%02X 0x%08X (current)", thread->current_priority, GetCurrentThread()->GetHandle());
281 for (Thread* t : thread_list) { 281 for (auto& t : thread_list) {
282 s32 priority = thread_ready_queue.contains(t); 282 s32 priority = thread_ready_queue.contains(t.get());
283 if (priority != -1) { 283 if (priority != -1) {
284 LOG_DEBUG(Kernel, "0x%02X 0x%08X", priority, t->GetHandle()); 284 LOG_DEBUG(Kernel, "0x%02X 0x%08X", priority, t->GetHandle());
285 } 285 }
286 } 286 }
287} 287}
288 288
289ResultVal<Thread*> Thread::Create(const char* name, u32 entry_point, s32 priority, u32 arg, 289ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, s32 priority,
290 s32 processor_id, u32 stack_top, int stack_size) { 290 u32 arg, s32 processor_id, VAddr stack_top, u32 stack_size) {
291 _dbg_assert_(Kernel, name != nullptr); 291 if (stack_size < 0x200) {
292 292 LOG_ERROR(Kernel, "(name=%s): invalid stack_size=0x%08X", name.c_str(), stack_size);
293 if ((u32)stack_size < 0x200) {
294 LOG_ERROR(Kernel, "(name=%s): invalid stack_size=0x%08X", name, stack_size);
295 // TODO: Verify error 293 // TODO: Verify error
296 return ResultCode(ErrorDescription::InvalidSize, ErrorModule::Kernel, 294 return ResultCode(ErrorDescription::InvalidSize, ErrorModule::Kernel,
297 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 295 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
@@ -300,27 +298,26 @@ ResultVal<Thread*> Thread::Create(const char* name, u32 entry_point, s32 priorit
300 if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) { 298 if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) {
301 s32 new_priority = CLAMP(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); 299 s32 new_priority = CLAMP(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST);
302 LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", 300 LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d",
303 name, priority, new_priority); 301 name.c_str(), priority, new_priority);
304 // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm 302 // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm
305 // validity of this 303 // validity of this
306 priority = new_priority; 304 priority = new_priority;
307 } 305 }
308 306
309 if (!Memory::GetPointer(entry_point)) { 307 if (!Memory::GetPointer(entry_point)) {
310 LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %08x", name, entry_point); 308 LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %08x", name.c_str(), entry_point);
311 // TODO: Verify error 309 // TODO: Verify error
312 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, 310 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
313 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 311 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
314 } 312 }
315 313
316 Thread* thread = new Thread; 314 SharedPtr<Thread> thread(new Thread);
317 315
318 // TODO(yuriks): Thread requires a handle to be inserted into the various scheduling queues for 316 // TODO(yuriks): Thread requires a handle to be inserted into the various scheduling queues for
319 // the time being. Create a handle here, it will be copied to the handle field in 317 // the time being. Create a handle here, it will be copied to the handle field in
320 // the object and use by the rest of the code. This should be removed when other 318 // the object and use by the rest of the code. This should be removed when other
321 // code doesn't rely on the handle anymore. 319 // code doesn't rely on the handle anymore.
322 ResultVal<Handle> handle = Kernel::g_handle_table.Create(thread); 320 ResultVal<Handle> handle = Kernel::g_handle_table.Create(thread);
323 // TODO(yuriks): Plug memory leak
324 if (handle.Failed()) 321 if (handle.Failed())
325 return handle.Code(); 322 return handle.Code();
326 323
@@ -337,12 +334,12 @@ ResultVal<Thread*> Thread::Create(const char* name, u32 entry_point, s32 priorit
337 thread->wait_type = WAITTYPE_NONE; 334 thread->wait_type = WAITTYPE_NONE;
338 thread->wait_object = nullptr; 335 thread->wait_object = nullptr;
339 thread->wait_address = 0; 336 thread->wait_address = 0;
340 thread->name = name; 337 thread->name = std::move(name);
341 338
342 ResetThread(thread, arg, 0); 339 ResetThread(thread.get(), arg, 0);
343 CallThread(thread); 340 CallThread(thread.get());
344 341
345 return MakeResult<Thread*>(thread); 342 return MakeResult<SharedPtr<Thread>>(std::move(thread));
346} 343}
347 344
348/// Set the priority of the thread specified by handle 345/// Set the priority of the thread specified by handle
@@ -376,20 +373,20 @@ Handle SetupIdleThread() {
376 auto thread_res = Thread::Create("idle", Memory::KERNEL_MEMORY_VADDR, THREADPRIO_LOWEST, 0, 373 auto thread_res = Thread::Create("idle", Memory::KERNEL_MEMORY_VADDR, THREADPRIO_LOWEST, 0,
377 THREADPROCESSORID_0, 0, Kernel::DEFAULT_STACK_SIZE); 374 THREADPROCESSORID_0, 0, Kernel::DEFAULT_STACK_SIZE);
378 _dbg_assert_(Kernel, thread_res.Succeeded()); 375 _dbg_assert_(Kernel, thread_res.Succeeded());
379 Thread* thread = *thread_res; 376 SharedPtr<Thread> thread = std::move(*thread_res);
380 377
381 thread->idle = true; 378 thread->idle = true;
382 CallThread(thread); 379 CallThread(thread.get());
383 return thread->GetHandle(); 380 return thread->GetHandle();
384} 381}
385 382
386Thread* SetupMainThread(s32 priority, int stack_size) { 383SharedPtr<Thread> SetupMainThread(s32 priority, u32 stack_size) {
387 // Initialize new "main" thread 384 // Initialize new "main" thread
388 ResultVal<Thread*> thread_res = Thread::Create("main", Core::g_app_core->GetPC(), priority, 0, 385 auto thread_res = Thread::Create("main", Core::g_app_core->GetPC(), priority, 0,
389 THREADPROCESSORID_0, Memory::SCRATCHPAD_VADDR_END, stack_size); 386 THREADPROCESSORID_0, Memory::SCRATCHPAD_VADDR_END, stack_size);
390 // TODO(yuriks): Propagate error 387 // TODO(yuriks): Propagate error
391 _dbg_assert_(Kernel, thread_res.Succeeded()); 388 _dbg_assert_(Kernel, thread_res.Succeeded());
392 Thread* thread = *thread_res; 389 SharedPtr<Thread> thread = std::move(*thread_res);
393 390
394 // If running another thread already, set it to "ready" state 391 // If running another thread already, set it to "ready" state
395 Thread* cur = GetCurrentThread(); 392 Thread* cur = GetCurrentThread();
@@ -398,7 +395,7 @@ Thread* SetupMainThread(s32 priority, int stack_size) {
398 } 395 }
399 396
400 // Run new "main" thread 397 // Run new "main" thread
401 current_thread = thread; 398 current_thread = thread.get();
402 thread->status = THREADSTATUS_RUNNING; 399 thread->status = THREADSTATUS_RUNNING;
403 Core::g_app_core->LoadContext(thread->context); 400 Core::g_app_core->LoadContext(thread->context);
404 401
@@ -418,7 +415,7 @@ void Reschedule() {
418 } else { 415 } else {
419 LOG_TRACE(Kernel, "cannot context switch from 0x%08X, no higher priority thread!", prev->GetHandle()); 416 LOG_TRACE(Kernel, "cannot context switch from 0x%08X, no higher priority thread!", prev->GetHandle());
420 417
421 for (Thread* thread : thread_list) { 418 for (auto& thread : thread_list) {
422 LOG_TRACE(Kernel, "\thandle=0x%08X prio=0x%02X, status=0x%08X wait_type=0x%08X wait_handle=0x%08X", 419 LOG_TRACE(Kernel, "\thandle=0x%08X prio=0x%02X, status=0x%08X wait_type=0x%08X wait_handle=0x%08X",
423 thread->GetHandle(), thread->current_priority, thread->status, thread->wait_type, 420 thread->GetHandle(), thread->current_priority, thread->status, thread->wait_type,
424 (thread->wait_object ? thread->wait_object->GetHandle() : INVALID_HANDLE)); 421 (thread->wait_object ? thread->wait_object->GetHandle() : INVALID_HANDLE));