diff options
Diffstat (limited to 'src/core/hle/kernel/thread.cpp')
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 63 |
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. |
| 39 | static std::vector<Thread*> thread_list; // TODO(yuriks): Owned | 39 | static std::vector<SharedPtr<Thread>> thread_list; |
| 40 | 40 | ||
| 41 | // Lists only ready thread ids. | 41 | // Lists only ready thread ids. |
| 42 | static Common::ThreadQueueList<Thread*, THREADPRIO_LOWEST+1> thread_ready_queue; | 42 | static 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) { | |||
| 168 | void ArbitrateAllThreads(Object* arbiter, u32 address) { | 168 | void 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 |
| 242 | static void ThreadWakeupCallback(u64 parameter, int cycles_late) { | 242 | static 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 | ||
| 289 | ResultVal<Thread*> Thread::Create(const char* name, u32 entry_point, s32 priority, u32 arg, | 289 | ResultVal<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 | ||
| 386 | Thread* SetupMainThread(s32 priority, int stack_size) { | 383 | SharedPtr<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)); |