From 733dfe220efc0f2488f104f7d7a5c1b31ba32e32 Mon Sep 17 00:00:00 2001 From: Subv Date: Mon, 21 Aug 2017 20:54:29 -0500 Subject: Kernel/Threads: Don't immediately switch to the new main thread when loading a new process. This is necessary for loading multiple processes at the same time. The main thread will be automatically scheduled when necessary once the scheduler runs. --- src/core/hle/kernel/thread.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'src/core/hle/kernel/thread.cpp') diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index f5f2eb2f7f..b957c45dd4 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -478,8 +478,6 @@ void Thread::BoostPriority(s32 priority) { } SharedPtr SetupMainThread(u32 entry_point, s32 priority) { - DEBUG_ASSERT(!GetCurrentThread()); - // Initialize new "main" thread auto thread_res = Thread::Create("main", entry_point, priority, 0, THREADPROCESSORID_0, Memory::HEAP_VADDR_END); @@ -489,9 +487,7 @@ SharedPtr SetupMainThread(u32 entry_point, s32 priority) { thread->context.fpscr = FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO | FPSCR_IXC; // 0x03C00010 - // Run new "main" thread - SwitchContext(thread.get()); - + // Note: The newly created thread will be run when the scheduler fires. return thread; } -- cgit v1.2.3 From 23ad87098d75346280cdb57235af5d02dfd377f0 Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 21 Jul 2017 21:28:03 -0500 Subject: Kernel/Memory: Switch the current page table when a new process is scheduled. --- src/core/hle/kernel/thread.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/core/hle/kernel/thread.cpp') diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index f5f2eb2f7f..b7f094f465 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -178,8 +178,18 @@ static void SwitchContext(Thread* new_thread) { Core::CPU().LoadContext(new_thread->context); Core::CPU().SetCP15Register(CP15_THREAD_URO, new_thread->GetTLSAddress()); + + if (!previous_thread || previous_thread->owner_process != current_thread->owner_process) { + Kernel::g_current_process = current_thread->owner_process; + Memory::current_page_table = &Kernel::g_current_process->vm_manager.page_table; + // We have switched processes and thus, page tables, clear the instruction cache so we + // don't keep stale data from the previous process. + Core::CPU().ClearInstructionCache(); + } } else { current_thread = nullptr; + // Note: We do not reset the current process and current page table when idling because + // technically we haven't changed processes, our threads are just paused. } } -- cgit v1.2.3 From 9200465e55105e4d8a9e4d6da288593430f902e1 Mon Sep 17 00:00:00 2001 From: Subv Date: Sat, 22 Jul 2017 19:37:26 -0500 Subject: Kernel/Threads: Don't clear the CPU instruction cache when performing a context switch from an idle thread into a thread in the same process. We were unnecessarily clearing the cache when going from Process A -> Idle -> Process A, this caused extreme performance regressions. --- src/core/hle/kernel/thread.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/core/hle/kernel/thread.cpp') diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index b7f094f465..f77c39d18d 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -171,6 +171,8 @@ static void SwitchContext(Thread* new_thread) { // Cancel any outstanding wakeup events for this thread CoreTiming::UnscheduleEvent(ThreadWakeupEventType, new_thread->callback_handle); + auto previous_process = Kernel::g_current_process; + current_thread = new_thread; ready_queue.remove(new_thread->current_priority, new_thread); @@ -179,7 +181,7 @@ static void SwitchContext(Thread* new_thread) { Core::CPU().LoadContext(new_thread->context); Core::CPU().SetCP15Register(CP15_THREAD_URO, new_thread->GetTLSAddress()); - if (!previous_thread || previous_thread->owner_process != current_thread->owner_process) { + if (previous_process != current_thread->owner_process) { Kernel::g_current_process = current_thread->owner_process; Memory::current_page_table = &Kernel::g_current_process->vm_manager.page_table; // We have switched processes and thus, page tables, clear the instruction cache so we -- cgit v1.2.3 From 6b8ad273fc79a78eddcb1fc2df440039ef0f5bf6 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sun, 24 Sep 2017 22:42:42 +0100 Subject: memory: Add GetCurrentPageTable/SetCurrentPageTable Don't expose Memory::current_page_table as a global. --- src/core/hle/kernel/thread.cpp | 11 ++++------- src/core/loader/3dsx.cpp | 2 +- src/core/loader/elf.cpp | 2 +- src/core/loader/ncch.cpp | 2 +- src/core/memory.cpp | 10 +++++++++- src/core/memory.h | 3 ++- src/tests/core/arm/arm_test_common.cpp | 2 +- 7 files changed, 19 insertions(+), 13 deletions(-) (limited to 'src/core/hle/kernel/thread.cpp') diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 324415a367..61378211fc 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -178,16 +178,13 @@ static void SwitchContext(Thread* new_thread) { ready_queue.remove(new_thread->current_priority, new_thread); new_thread->status = THREADSTATUS_RUNNING; - Core::CPU().LoadContext(new_thread->context); - Core::CPU().SetCP15Register(CP15_THREAD_URO, new_thread->GetTLSAddress()); - if (previous_process != current_thread->owner_process) { Kernel::g_current_process = current_thread->owner_process; - Memory::current_page_table = &Kernel::g_current_process->vm_manager.page_table; - // We have switched processes and thus, page tables, clear the instruction cache so we - // don't keep stale data from the previous process. - Core::CPU().ClearInstructionCache(); + SetCurrentPageTable(&Kernel::g_current_process->vm_manager.page_table); } + + Core::CPU().LoadContext(new_thread->context); + Core::CPU().SetCP15Register(CP15_THREAD_URO, new_thread->GetTLSAddress()); } else { current_thread = nullptr; // Note: We do not reset the current process and current page table when idling because diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp index 69cdc0867e..a03515e6ec 100644 --- a/src/core/loader/3dsx.cpp +++ b/src/core/loader/3dsx.cpp @@ -270,7 +270,7 @@ ResultStatus AppLoader_THREEDSX::Load() { Kernel::g_current_process = Kernel::Process::Create(std::move(codeset)); Kernel::g_current_process->svc_access_mask.set(); Kernel::g_current_process->address_mappings = default_address_mappings; - Memory::current_page_table = &Kernel::g_current_process->vm_manager.page_table; + Memory::SetCurrentPageTable(&Kernel::g_current_process->vm_manager.page_table); // Attach the default resource limit (APPLICATION) to the process Kernel::g_current_process->resource_limit = diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp index 2f27606a18..2de1f4e816 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp @@ -397,7 +397,7 @@ ResultStatus AppLoader_ELF::Load() { Kernel::g_current_process = Kernel::Process::Create(std::move(codeset)); Kernel::g_current_process->svc_access_mask.set(); Kernel::g_current_process->address_mappings = default_address_mappings; - Memory::current_page_table = &Kernel::g_current_process->vm_manager.page_table; + Memory::SetCurrentPageTable(&Kernel::g_current_process->vm_manager.page_table); // Attach the default resource limit (APPLICATION) to the process Kernel::g_current_process->resource_limit = diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp index 79ea501471..ca282f9352 100644 --- a/src/core/loader/ncch.cpp +++ b/src/core/loader/ncch.cpp @@ -172,7 +172,7 @@ ResultStatus AppLoader_NCCH::LoadExec() { codeset->memory = std::make_shared>(std::move(code)); Kernel::g_current_process = Kernel::Process::Create(std::move(codeset)); - Memory::current_page_table = &Kernel::g_current_process->vm_manager.page_table; + Memory::SetCurrentPageTable(&Kernel::g_current_process->vm_manager.page_table); // Attach a resource limit to the process based on the resource limit category Kernel::g_current_process->resource_limit = diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 68a6b1ac26..17fa10b499 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -22,12 +22,20 @@ namespace Memory { static std::array vram; static std::array n3ds_extra_ram; -PageTable* current_page_table = nullptr; +static PageTable* current_page_table = nullptr; std::array* GetCurrentPageTablePointers() { return ¤t_page_table->pointers; } +void SetCurrentPageTable(PageTable* page_table) { + current_page_table = page_table; +} + +PageTable* GetCurrentPageTable() { + return current_page_table; +} + static void MapPages(PageTable& page_table, u32 base, u32 size, u8* memory, PageType type) { LOG_DEBUG(HW_Memory, "Mapping %p onto %08X-%08X", memory, base * PAGE_SIZE, (base + size) * PAGE_SIZE); diff --git a/src/core/memory.h b/src/core/memory.h index b228a48c2e..db5a704d0f 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -182,7 +182,8 @@ enum : VAddr { }; /// Currently active page table -extern PageTable* current_page_table; +void SetCurrentPageTable(PageTable* page_table); +PageTable* GetCurrentPageTable(); bool IsValidVirtualAddress(const VAddr addr); bool IsValidPhysicalAddress(const PAddr addr); diff --git a/src/tests/core/arm/arm_test_common.cpp b/src/tests/core/arm/arm_test_common.cpp index 8384ce7440..cfe0d503ae 100644 --- a/src/tests/core/arm/arm_test_common.cpp +++ b/src/tests/core/arm/arm_test_common.cpp @@ -21,7 +21,7 @@ TestEnvironment::TestEnvironment(bool mutable_memory_) Memory::MapIoRegion(page_table, 0x00000000, 0x80000000, test_memory); Memory::MapIoRegion(page_table, 0x80000000, 0x80000000, test_memory); - Memory::current_page_table = &page_table; + Memory::SetCurrentPageTable(&page_table); } TestEnvironment::~TestEnvironment() { -- cgit v1.2.3 From 2e78c05d91bea844eba9b80a3df1abcc70ffb4fc Mon Sep 17 00:00:00 2001 From: Subv Date: Tue, 26 Sep 2017 17:40:49 -0500 Subject: Kernel/Thread: Allow specifying which process a thread belongs to when creating it. Don't automatically assume that Thread::Create will only be called when the parent process is currently scheduled. This assumption will be broken when applets or system modules are loaded. --- src/core/hle/kernel/process.cpp | 2 +- src/core/hle/kernel/thread.cpp | 17 +++++++++-------- src/core/hle/kernel/thread.h | 15 +++++++++------ src/core/hle/svc.cpp | 5 +++-- 4 files changed, 22 insertions(+), 17 deletions(-) (limited to 'src/core/hle/kernel/thread.cpp') diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 522ad2333c..cf3163e0fe 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -147,7 +147,7 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) { } vm_manager.LogLayout(Log::Level::Debug); - Kernel::SetupMainThread(codeset->entrypoint, main_thread_priority); + Kernel::SetupMainThread(codeset->entrypoint, main_thread_priority, this); } VAddr Process::GetLinearHeapAreaAddress() const { diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 61378211fc..1033f8552e 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -361,7 +361,8 @@ static void ResetThreadContext(ARM_Interface::ThreadContext& context, u32 stack_ } ResultVal> Thread::Create(std::string name, VAddr entry_point, u32 priority, - u32 arg, s32 processor_id, VAddr stack_top) { + u32 arg, s32 processor_id, VAddr stack_top, + SharedPtr owner_process) { // Check if priority is in ranged. Lowest priority -> highest priority id. if (priority > THREADPRIO_LOWEST) { LOG_ERROR(Kernel_SVC, "Invalid thread priority: %d", priority); @@ -375,7 +376,7 @@ ResultVal> Thread::Create(std::string name, VAddr entry_point, // TODO(yuriks): Other checks, returning 0xD9001BEA - if (!Memory::IsValidVirtualAddress(entry_point)) { + if (!Memory::IsValidVirtualAddress(*owner_process, entry_point)) { LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %08x", name.c_str(), entry_point); // TODO: Verify error return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, @@ -399,10 +400,10 @@ ResultVal> Thread::Create(std::string name, VAddr entry_point, thread->wait_address = 0; thread->name = std::move(name); thread->callback_handle = wakeup_callback_handle_table.Create(thread).Unwrap(); - thread->owner_process = g_current_process; + thread->owner_process = owner_process; // Find the next available TLS index, and mark it as used - auto& tls_slots = Kernel::g_current_process->tls_slots; + auto& tls_slots = owner_process->tls_slots; bool needs_allocation = true; u32 available_page; // Which allocated page has free space u32 available_slot; // Which slot within the page is free @@ -426,13 +427,13 @@ ResultVal> Thread::Create(std::string name, VAddr entry_point, // Allocate some memory from the end of the linear heap for this region. linheap_memory->insert(linheap_memory->end(), Memory::PAGE_SIZE, 0); memory_region->used += Memory::PAGE_SIZE; - Kernel::g_current_process->linear_heap_used += Memory::PAGE_SIZE; + owner_process->linear_heap_used += Memory::PAGE_SIZE; tls_slots.emplace_back(0); // The page is completely available at the start available_page = tls_slots.size() - 1; available_slot = 0; // Use the first slot in the new page - auto& vm_manager = Kernel::g_current_process->vm_manager; + auto& vm_manager = owner_process->vm_manager; vm_manager.RefreshMemoryBlockMappings(linheap_memory.get()); // Map the page to the current process' address space. @@ -486,10 +487,10 @@ void Thread::BoostPriority(s32 priority) { current_priority = priority; } -SharedPtr SetupMainThread(u32 entry_point, s32 priority) { +SharedPtr SetupMainThread(u32 entry_point, s32 priority, SharedPtr owner_process) { // Initialize new "main" thread auto thread_res = Thread::Create("main", entry_point, priority, 0, THREADPROCESSORID_0, - Memory::HEAP_VADDR_END); + Memory::HEAP_VADDR_END, owner_process); SharedPtr thread = std::move(thread_res).Unwrap(); diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 6a3566f15b..ddc0d15c56 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -56,10 +56,12 @@ public: * @param arg User data to pass to the thread * @param processor_id The ID(s) of the processors on which the thread is desired to be run * @param stack_top The address of the thread's stack top + * @param owner_process The parent process for the thread * @return A shared pointer to the newly created thread */ static ResultVal> Create(std::string name, VAddr entry_point, u32 priority, - u32 arg, s32 processor_id, VAddr stack_top); + u32 arg, s32 processor_id, VAddr stack_top, + SharedPtr owner_process); std::string GetName() const override { return name; @@ -116,9 +118,9 @@ public: void ResumeFromWait(); /** - * Schedules an event to wake up the specified thread after the specified delay - * @param nanoseconds The time this thread will be allowed to sleep for - */ + * Schedules an event to wake up the specified thread after the specified delay + * @param nanoseconds The time this thread will be allowed to sleep for + */ void WakeAfterDelay(s64 nanoseconds); /** @@ -214,9 +216,10 @@ private: * Sets up the primary application thread * @param entry_point The address at which the thread should start execution * @param priority The priority to give the main thread + * @param owner_process The parent process for the main thread * @return A shared pointer to the main thread */ -SharedPtr SetupMainThread(u32 entry_point, s32 priority); +SharedPtr SetupMainThread(u32 entry_point, s32 priority, SharedPtr owner_process); /** * Returns whether there are any threads that are ready to run. @@ -276,4 +279,4 @@ void ThreadingShutdown(); */ const std::vector>& GetThreadList(); -} // namespace +} // namespace Kernel diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index dfc36748c1..05c6897bf8 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -656,8 +656,9 @@ static ResultCode CreateThread(Kernel::Handle* out_handle, u32 priority, u32 ent "Newly created thread must run in the SysCore (Core1), unimplemented."); } - CASCADE_RESULT(SharedPtr thread, Kernel::Thread::Create(name, entry_point, priority, - arg, processor_id, stack_top)); + CASCADE_RESULT(SharedPtr thread, + Kernel::Thread::Create(name, entry_point, priority, arg, processor_id, stack_top, + Kernel::g_current_process)); thread->context.fpscr = FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO; // 0x03C00000 -- cgit v1.2.3 From a0054d695e02fd7552101df77cbe1eadf72593d4 Mon Sep 17 00:00:00 2001 From: Subv Date: Thu, 28 Sep 2017 11:53:32 -0500 Subject: Kernel/Threads: When putting a thread to wait, specify a function to execute when it is awoken. This change makes for a clearer (less confusing) path of execution in the scheduler, now the code to execute when a thread awakes is closer to the code that puts the thread to sleep (WaitSynch1, WaitSynchN). It also allows us to implement the special wake up behavior of ReplyAndReceive without hacking up WaitObject::WakeupAllWaitingThreads. If savestates are desired in the future, we can change this implementation to one similar to the CoreTiming event system, where we first register the callback functions at startup and assign their identifiers to the Thread callback variable instead of directly assigning a lambda to the wake up callback variable. --- src/core/hle/kernel/thread.cpp | 13 +++++-- src/core/hle/kernel/thread.h | 15 ++++++-- src/core/hle/kernel/wait_object.cpp | 11 +++--- src/core/hle/svc.cpp | 69 ++++++++++++++++++++++++++++++++++--- 4 files changed, 91 insertions(+), 17 deletions(-) (limited to 'src/core/hle/kernel/thread.cpp') diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 61378211fc..690cb20b39 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -247,12 +247,15 @@ static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) { if (thread->status == THREADSTATUS_WAIT_SYNCH_ANY || thread->status == THREADSTATUS_WAIT_SYNCH_ALL || thread->status == THREADSTATUS_WAIT_ARB) { - thread->wait_set_output = false; + + // Invoke the wakeup callback before clearing the wait objects + if (thread->wakeup_callback) + thread->wakeup_callback(ThreadWakeupReason::Timeout, thread, nullptr); + // Remove the thread from each of its waiting objects' waitlists for (auto& object : thread->wait_objects) object->RemoveWaitingThread(thread.get()); thread->wait_objects.clear(); - thread->SetWaitSynchronizationResult(RESULT_TIMEOUT); } thread->ResumeFromWait(); @@ -278,6 +281,9 @@ void Thread::ResumeFromWait() { break; case THREADSTATUS_READY: + // The thread's wakeup callback must have already been cleared when the thread was first + // awoken. + ASSERT(wakeup_callback == nullptr); // If the thread is waiting on multiple wait objects, it might be awoken more than once // before actually resuming. We can ignore subsequent wakeups if the thread status has // already been set to THREADSTATUS_READY. @@ -293,6 +299,8 @@ void Thread::ResumeFromWait() { return; } + wakeup_callback = nullptr; + ready_queue.push_back(current_priority, this); status = THREADSTATUS_READY; Core::System::GetInstance().PrepareReschedule(); @@ -394,7 +402,6 @@ ResultVal> Thread::Create(std::string name, VAddr entry_point, thread->nominal_priority = thread->current_priority = priority; thread->last_running_ticks = CoreTiming::GetTicks(); thread->processor_id = processor_id; - thread->wait_set_output = false; thread->wait_objects.clear(); thread->wait_address = 0; thread->name = std::move(name); diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 6a3566f15b..328f1a86aa 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -41,6 +41,11 @@ enum ThreadStatus { THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated }; +enum class ThreadWakeupReason { + Signal, // The thread was woken up by WakeupAllWaitingThreads due to an object signal. + Timeout // The thread was woken up due to a wait timeout. +}; + namespace Kernel { class Mutex; @@ -197,14 +202,18 @@ public: VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address - /// True if the WaitSynchronizationN output parameter should be set on thread wakeup. - bool wait_set_output; - std::string name; /// Handle used as userdata to reference this object when inserting into the CoreTiming queue. Handle callback_handle; + using WakeupCallback = void(ThreadWakeupReason reason, SharedPtr thread, + SharedPtr object); + // Callback that will be invoked when the thread is resumed from a waiting state. If the thread + // was waiting via WaitSynchronizationN then the object will be the last object that became + // available. In case of a timeout, the object will be nullptr. + std::function wakeup_callback; + private: Thread(); ~Thread() override; diff --git a/src/core/hle/kernel/wait_object.cpp b/src/core/hle/kernel/wait_object.cpp index f245eda6cd..1ced26905a 100644 --- a/src/core/hle/kernel/wait_object.cpp +++ b/src/core/hle/kernel/wait_object.cpp @@ -71,23 +71,20 @@ void WaitObject::WakeupAllWaitingThreads() { while (auto thread = GetHighestPriorityReadyThread()) { if (!thread->IsSleepingOnWaitAll()) { Acquire(thread.get()); - // Set the output index of the WaitSynchronizationN call to the index of this object. - if (thread->wait_set_output) { - thread->SetWaitSynchronizationOutput(thread->GetWaitObjectIndex(this)); - thread->wait_set_output = false; - } } else { for (auto& object : thread->wait_objects) { object->Acquire(thread.get()); } - // Note: This case doesn't update the output index of WaitSynchronizationN. } + // Invoke the wakeup callback before clearing the wait objects + if (thread->wakeup_callback) + thread->wakeup_callback(ThreadWakeupReason::Signal, thread, this); + for (auto& object : thread->wait_objects) object->RemoveWaitingThread(thread.get()); thread->wait_objects.clear(); - thread->SetWaitSynchronizationResult(RESULT_SUCCESS); thread->ResumeFromWait(); } } diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index dfc36748c1..41e62cf622 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -271,6 +271,24 @@ static ResultCode WaitSynchronization1(Kernel::Handle handle, s64 nano_seconds) // Create an event to wake the thread up after the specified nanosecond delay has passed thread->WakeAfterDelay(nano_seconds); + thread->wakeup_callback = [](ThreadWakeupReason reason, + Kernel::SharedPtr thread, + Kernel::SharedPtr object) { + + ASSERT(thread->status == THREADSTATUS_WAIT_SYNCH_ANY); + + if (reason == ThreadWakeupReason::Timeout) { + thread->SetWaitSynchronizationResult(Kernel::RESULT_TIMEOUT); + return; + } + + ASSERT(reason == ThreadWakeupReason::Signal); + thread->SetWaitSynchronizationResult(RESULT_SUCCESS); + + // WaitSynchronization1 doesn't have an output index like WaitSynchronizationN, so we + // don't have to do anything else here. + }; + Core::System::GetInstance().PrepareReschedule(); // Note: The output of this SVC will be set to RESULT_SUCCESS if the thread @@ -344,6 +362,23 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha // Create an event to wake the thread up after the specified nanosecond delay has passed thread->WakeAfterDelay(nano_seconds); + thread->wakeup_callback = [](ThreadWakeupReason reason, + Kernel::SharedPtr thread, + Kernel::SharedPtr object) { + + ASSERT(thread->status == THREADSTATUS_WAIT_SYNCH_ALL); + + if (reason == ThreadWakeupReason::Timeout) { + thread->SetWaitSynchronizationResult(Kernel::RESULT_TIMEOUT); + return; + } + + ASSERT(reason == ThreadWakeupReason::Signal); + + thread->SetWaitSynchronizationResult(RESULT_SUCCESS); + // The wait_all case does not update the output index. + }; + Core::System::GetInstance().PrepareReschedule(); // This value gets set to -1 by default in this case, it is not modified after this. @@ -389,12 +424,28 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha // Create an event to wake the thread up after the specified nanosecond delay has passed thread->WakeAfterDelay(nano_seconds); + thread->wakeup_callback = [](ThreadWakeupReason reason, + Kernel::SharedPtr thread, + Kernel::SharedPtr object) { + + ASSERT(thread->status == THREADSTATUS_WAIT_SYNCH_ANY); + + if (reason == ThreadWakeupReason::Timeout) { + thread->SetWaitSynchronizationResult(Kernel::RESULT_TIMEOUT); + return; + } + + ASSERT(reason == ThreadWakeupReason::Signal); + + thread->SetWaitSynchronizationResult(RESULT_SUCCESS); + thread->SetWaitSynchronizationOutput(thread->GetWaitObjectIndex(object.get())); + }; + Core::System::GetInstance().PrepareReschedule(); // Note: The output of this SVC will be set to RESULT_SUCCESS if the thread resumes due to a // signal in one of its wait objects. // Otherwise we retain the default value of timeout, and -1 in the out parameter - thread->wait_set_output = true; *out = -1; return Kernel::RESULT_TIMEOUT; } @@ -483,8 +534,6 @@ static ResultCode ReplyAndReceive(s32* index, Kernel::Handle* handles, s32 handl // No objects were ready to be acquired, prepare to suspend the thread. - // TODO(Subv): Perform IPC translation upon wakeup. - // Put the thread to sleep thread->status = THREADSTATUS_WAIT_SYNCH_ANY; @@ -496,12 +545,24 @@ static ResultCode ReplyAndReceive(s32* index, Kernel::Handle* handles, s32 handl thread->wait_objects = std::move(objects); + thread->wakeup_callback = [](ThreadWakeupReason reason, + Kernel::SharedPtr thread, + Kernel::SharedPtr object) { + + ASSERT(thread->status == THREADSTATUS_WAIT_SYNCH_ANY); + ASSERT(reason == ThreadWakeupReason::Signal); + + thread->SetWaitSynchronizationResult(RESULT_SUCCESS); + thread->SetWaitSynchronizationOutput(thread->GetWaitObjectIndex(object.get())); + + // TODO(Subv): Perform IPC translation upon wakeup. + }; + Core::System::GetInstance().PrepareReschedule(); // Note: The output of this SVC will be set to RESULT_SUCCESS if the thread resumes due to a // signal in one of its wait objects, or to 0xC8A01836 if there was a translation error. // By default the index is set to -1. - thread->wait_set_output = true; *index = -1; return RESULT_SUCCESS; } -- cgit v1.2.3 From da1c8d152285c5ed4b2dcb9915b886555c99610f Mon Sep 17 00:00:00 2001 From: Huw Pascoe Date: Wed, 27 Sep 2017 00:26:09 +0100 Subject: Fixed type conversion ambiguity --- src/audio_core/hle/source.cpp | 2 +- .../debugger/graphics/graphics_cmdlists.cpp | 4 +-- .../debugger/graphics/graphics_surface.cpp | 3 +- src/common/string_util.cpp | 2 +- src/common/string_util.h | 2 +- src/common/vector_math.h | 12 ++------ src/core/gdbstub/gdbstub.cpp | 4 +-- src/core/hle/ipc.h | 8 ++--- src/core/hle/ipc_helpers.h | 12 ++++---- src/core/hle/kernel/hle_ipc.cpp | 2 +- src/core/hle/kernel/mutex.cpp | 2 +- src/core/hle/kernel/resource_limit.cpp | 2 +- src/core/hle/kernel/resource_limit.h | 2 +- src/core/hle/kernel/shared_memory.cpp | 3 +- src/core/hle/kernel/shared_memory.h | 2 +- src/core/hle/kernel/thread.cpp | 18 +++++------ src/core/hle/kernel/thread.h | 14 ++++----- src/core/hle/kernel/wait_object.cpp | 2 +- src/core/hle/service/apt/apt.cpp | 4 +-- src/core/hle/service/cam/cam.cpp | 2 +- src/core/hle/service/cfg/cfg.cpp | 2 +- src/core/hle/service/fs/archive.cpp | 2 +- src/core/hle/service/hid/hid.cpp | 2 +- src/core/hle/service/ldr_ro/cro_helper.h | 6 ++-- src/core/hle/service/nwm/nwm_uds.cpp | 10 +++--- src/core/hle/service/nwm/uds_beacon.cpp | 4 +-- src/core/hle/service/nwm/uds_data.cpp | 8 ++--- src/core/hle/svc.cpp | 8 ++--- src/core/memory.cpp | 36 +++++++++++++--------- src/network/packet.cpp | 2 +- src/video_core/geometry_pipeline.cpp | 2 +- src/video_core/renderer_opengl/gl_state.cpp | 4 +-- 32 files changed, 97 insertions(+), 91 deletions(-) (limited to 'src/core/hle/kernel/thread.cpp') diff --git a/src/audio_core/hle/source.cpp b/src/audio_core/hle/source.cpp index de4e88caee..c122877002 100644 --- a/src/audio_core/hle/source.cpp +++ b/src/audio_core/hle/source.cpp @@ -264,7 +264,7 @@ void Source::GenerateFrame() { break; } } - state.next_sample_number += frame_position; + state.next_sample_number += static_cast(frame_position); state.filters.ProcessFrame(current_frame); } diff --git a/src/citra_qt/debugger/graphics/graphics_cmdlists.cpp b/src/citra_qt/debugger/graphics/graphics_cmdlists.cpp index 7d06ec28a4..ce2b9fa505 100644 --- a/src/citra_qt/debugger/graphics/graphics_cmdlists.cpp +++ b/src/citra_qt/debugger/graphics/graphics_cmdlists.cpp @@ -26,8 +26,8 @@ namespace { QImage LoadTexture(const u8* src, const Pica::Texture::TextureInfo& info) { QImage decoded_image(info.width, info.height, QImage::Format_ARGB32); - for (int y = 0; y < info.height; ++y) { - for (int x = 0; x < info.width; ++x) { + for (u32 y = 0; y < info.height; ++y) { + for (u32 x = 0; x < info.width; ++x) { Math::Vec4 color = Pica::Texture::LookupTexture(src, x, y, info, true); decoded_image.setPixel(x, y, qRgba(color.r(), color.g(), color.b(), color.a())); } diff --git a/src/citra_qt/debugger/graphics/graphics_surface.cpp b/src/citra_qt/debugger/graphics/graphics_surface.cpp index 47d9924e1a..c974545ef2 100644 --- a/src/citra_qt/debugger/graphics/graphics_surface.cpp +++ b/src/citra_qt/debugger/graphics/graphics_surface.cpp @@ -273,7 +273,8 @@ void GraphicsSurfaceWidget::Pick(int x, int y) { surface_picker_x_control->setValue(x); surface_picker_y_control->setValue(y); - if (x < 0 || x >= surface_width || y < 0 || y >= surface_height) { + if (x < 0 || x >= static_cast(surface_width) || y < 0 || + y >= static_cast(surface_height)) { surface_info_label->setText(tr("Pixel out of bounds")); surface_info_label->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); return; diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp index bad311793d..6959915faa 100644 --- a/src/common/string_util.cpp +++ b/src/common/string_util.cpp @@ -117,7 +117,7 @@ std::string StringFromFormat(const char* format, ...) { } // For Debugging. Read out an u8 array. -std::string ArrayToString(const u8* data, u32 size, int line_len, bool spaces) { +std::string ArrayToString(const u8* data, size_t size, int line_len, bool spaces) { std::ostringstream oss; oss << std::setfill('0') << std::hex; diff --git a/src/common/string_util.h b/src/common/string_util.h index 075bf4ecb2..259360aecb 100644 --- a/src/common/string_util.h +++ b/src/common/string_util.h @@ -33,7 +33,7 @@ inline void CharArrayFromFormat(char (&out)[Count], const char* format, ...) { } // Good -std::string ArrayToString(const u8* data, u32 size, int line_len = 20, bool spaces = true); +std::string ArrayToString(const u8* data, size_t size, int line_len = 20, bool spaces = true); std::string StripSpaces(const std::string& s); std::string StripQuotes(const std::string& s); diff --git a/src/common/vector_math.h b/src/common/vector_math.h index 2b05f66eef..3f0057d9e5 100644 --- a/src/common/vector_math.h +++ b/src/common/vector_math.h @@ -104,8 +104,7 @@ public: } template void operator*=(const V& f) { - x *= f; - y *= f; + *this = *this * f; } template Vec2 operator/(const V& f) const { @@ -262,9 +261,7 @@ public: } template void operator*=(const V& f) { - x *= f; - y *= f; - z *= f; + *this = *this * f; } template Vec3 operator/(const V& f) const { @@ -478,10 +475,7 @@ public: } template void operator*=(const V& f) { - x *= f; - y *= f; - z *= f; - w *= f; + *this = *this * f; } template Vec4 operator/(const V& f) const { diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp index 123fe7cd4b..be2b2e25f3 100644 --- a/src/core/gdbstub/gdbstub.cpp +++ b/src/core/gdbstub/gdbstub.cpp @@ -946,7 +946,7 @@ static void Init(u16 port) { WSAStartup(MAKEWORD(2, 2), &InitData); #endif - int tmpsock = socket(PF_INET, SOCK_STREAM, 0); + int tmpsock = static_cast(socket(PF_INET, SOCK_STREAM, 0)); if (tmpsock == -1) { LOG_ERROR(Debug_GDBStub, "Failed to create gdb socket"); } @@ -973,7 +973,7 @@ static void Init(u16 port) { sockaddr_in saddr_client; sockaddr* client_addr = reinterpret_cast(&saddr_client); socklen_t client_addrlen = sizeof(saddr_client); - gdbserver_socket = accept(tmpsock, client_addr, &client_addrlen); + gdbserver_socket = static_cast(accept(tmpsock, client_addr, &client_addrlen)); if (gdbserver_socket < 0) { // In the case that we couldn't start the server for whatever reason, just start CPU // execution like normal. diff --git a/src/core/hle/ipc.h b/src/core/hle/ipc.h index f7f96125ab..87ed85df68 100644 --- a/src/core/hle/ipc.h +++ b/src/core/hle/ipc.h @@ -122,11 +122,11 @@ union StaticBufferDescInfo { BitField<14, 18, u32> size; }; -inline u32 StaticBufferDesc(u32 size, u8 buffer_id) { +inline u32 StaticBufferDesc(size_t size, u8 buffer_id) { StaticBufferDescInfo info{}; info.descriptor_type.Assign(StaticBuffer); info.buffer_id.Assign(buffer_id); - info.size.Assign(size); + info.size.Assign(static_cast(size)); return info.raw; } @@ -160,11 +160,11 @@ union MappedBufferDescInfo { BitField<4, 28, u32> size; }; -inline u32 MappedBufferDesc(u32 size, MappedBufferPermissions perms) { +inline u32 MappedBufferDesc(size_t size, MappedBufferPermissions perms) { MappedBufferDescInfo info{}; info.flags.Assign(MappedBuffer); info.perms.Assign(perms); - info.size.Assign(size); + info.size.Assign(static_cast(size)); return info.raw; } diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h index f0d89cffe6..7cb95cbacb 100644 --- a/src/core/hle/ipc_helpers.h +++ b/src/core/hle/ipc_helpers.h @@ -117,9 +117,9 @@ public: void PushCurrentPIDHandle(); - void PushStaticBuffer(VAddr buffer_vaddr, u32 size, u8 buffer_id); + void PushStaticBuffer(VAddr buffer_vaddr, size_t size, u8 buffer_id); - void PushMappedBuffer(VAddr buffer_vaddr, u32 size, MappedBufferPermissions perms); + void PushMappedBuffer(VAddr buffer_vaddr, size_t size, MappedBufferPermissions perms); }; /// Push /// @@ -190,12 +190,12 @@ inline void RequestBuilder::PushCurrentPIDHandle() { Push(u32(0)); } -inline void RequestBuilder::PushStaticBuffer(VAddr buffer_vaddr, u32 size, u8 buffer_id) { +inline void RequestBuilder::PushStaticBuffer(VAddr buffer_vaddr, size_t size, u8 buffer_id) { Push(StaticBufferDesc(size, buffer_id)); Push(buffer_vaddr); } -inline void RequestBuilder::PushMappedBuffer(VAddr buffer_vaddr, u32 size, +inline void RequestBuilder::PushMappedBuffer(VAddr buffer_vaddr, size_t size, MappedBufferPermissions perms) { Push(MappedBufferDesc(size, perms)); Push(buffer_vaddr); @@ -227,8 +227,8 @@ public: bool validateHeader = true) { if (validateHeader) ValidateHeader(); - Header builderHeader{ - MakeHeader(header.command_id, normal_params_size, translate_params_size)}; + Header builderHeader{MakeHeader(static_cast(header.command_id), normal_params_size, + translate_params_size)}; if (context != nullptr) return {*context, builderHeader}; else diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 5ebe2eca4a..6020e9764e 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -37,7 +37,7 @@ SharedPtr HLERequestContext::GetIncomingHandle(u32 id_from_cmdbuf) const u32 HLERequestContext::AddOutgoingHandle(SharedPtr object) { request_handles.push_back(std::move(object)); - return request_handles.size() - 1; + return static_cast(request_handles.size() - 1); } void HLERequestContext::ClearIncomingObjects() { diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index cef9612899..2cbca5e5be 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -90,7 +90,7 @@ void Mutex::UpdatePriority() { if (!holding_thread) return; - s32 best_priority = THREADPRIO_LOWEST; + u32 best_priority = THREADPRIO_LOWEST; for (auto& waiter : GetWaitingThreads()) { if (waiter->current_priority < best_priority) best_priority = waiter->current_priority; diff --git a/src/core/hle/kernel/resource_limit.cpp b/src/core/hle/kernel/resource_limit.cpp index a8f10a3eeb..517dc47a8c 100644 --- a/src/core/hle/kernel/resource_limit.cpp +++ b/src/core/hle/kernel/resource_limit.cpp @@ -61,7 +61,7 @@ s32 ResourceLimit::GetCurrentResourceValue(u32 resource) const { } } -s32 ResourceLimit::GetMaxResourceValue(u32 resource) const { +u32 ResourceLimit::GetMaxResourceValue(u32 resource) const { switch (resource) { case PRIORITY: return max_priority; diff --git a/src/core/hle/kernel/resource_limit.h b/src/core/hle/kernel/resource_limit.h index 6cdfbcf8db..42874eb8dd 100644 --- a/src/core/hle/kernel/resource_limit.h +++ b/src/core/hle/kernel/resource_limit.h @@ -67,7 +67,7 @@ public: * @param resource Requested resource type * @returns The max value of the resource type */ - s32 GetMaxResourceValue(u32 resource) const; + u32 GetMaxResourceValue(u32 resource) const; /// Name of resource limit object. std::string name; diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp index a7b66142f6..02d5a7a360 100644 --- a/src/core/hle/kernel/shared_memory.cpp +++ b/src/core/hle/kernel/shared_memory.cpp @@ -42,7 +42,8 @@ SharedPtr SharedMemory::Create(SharedPtr owner_process, u memory_region->used += size; shared_memory->linear_heap_phys_address = - Memory::FCRAM_PADDR + memory_region->base + shared_memory->backing_block_offset; + Memory::FCRAM_PADDR + memory_region->base + + static_cast(shared_memory->backing_block_offset); // Increase the amount of used linear heap memory for the owner process. if (shared_memory->owner_process != nullptr) { diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h index 94b335ed12..93a6f21822 100644 --- a/src/core/hle/kernel/shared_memory.h +++ b/src/core/hle/kernel/shared_memory.h @@ -114,7 +114,7 @@ public: /// Backing memory for this shared memory block. std::shared_ptr> backing_block; /// Offset into the backing block for this shared memory. - u32 backing_block_offset; + size_t backing_block_offset; /// Size of the memory block. Page-aligned. u32 size; /// Permission restrictions applied to the process which created the block. diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 1033f8552e..11f7d21277 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -111,7 +111,7 @@ void Thread::Stop() { Thread* ArbitrateHighestPriorityThread(u32 address) { Thread* highest_priority_thread = nullptr; - s32 priority = THREADPRIO_LOWEST; + u32 priority = THREADPRIO_LOWEST; // Iterate through threads, find highest priority thread that is waiting to be arbitrated... for (auto& thread : thread_list) { @@ -311,7 +311,7 @@ static void DebugThreadQueue() { } for (auto& t : thread_list) { - s32 priority = ready_queue.contains(t.get()); + u32 priority = ready_queue.contains(t.get()); if (priority != -1) { LOG_DEBUG(Kernel, "0x%02X %u", priority, t->GetObjectId()); } @@ -422,7 +422,7 @@ ResultVal> Thread::Create(std::string name, VAddr entry_point, return ERR_OUT_OF_MEMORY; } - u32 offset = linheap_memory->size(); + size_t offset = linheap_memory->size(); // Allocate some memory from the end of the linear heap for this region. linheap_memory->insert(linheap_memory->end(), Memory::PAGE_SIZE, 0); @@ -430,7 +430,7 @@ ResultVal> Thread::Create(std::string name, VAddr entry_point, owner_process->linear_heap_used += Memory::PAGE_SIZE; tls_slots.emplace_back(0); // The page is completely available at the start - available_page = tls_slots.size() - 1; + available_page = static_cast(tls_slots.size() - 1); available_slot = 0; // Use the first slot in the new page auto& vm_manager = owner_process->vm_manager; @@ -457,7 +457,7 @@ ResultVal> Thread::Create(std::string name, VAddr entry_point, return MakeResult>(std::move(thread)); } -void Thread::SetPriority(s32 priority) { +void Thread::SetPriority(u32 priority) { ASSERT_MSG(priority <= THREADPRIO_LOWEST && priority >= THREADPRIO_HIGHEST, "Invalid priority value."); // If thread was ready, adjust queues @@ -470,7 +470,7 @@ void Thread::SetPriority(s32 priority) { } void Thread::UpdatePriority() { - s32 best_priority = nominal_priority; + u32 best_priority = nominal_priority; for (auto& mutex : held_mutexes) { if (mutex->priority < best_priority) best_priority = mutex->priority; @@ -478,7 +478,7 @@ void Thread::UpdatePriority() { BoostPriority(best_priority); } -void Thread::BoostPriority(s32 priority) { +void Thread::BoostPriority(u32 priority) { // If thread was ready, adjust queues if (status == THREADSTATUS_READY) ready_queue.move(this, current_priority, priority); @@ -487,7 +487,7 @@ void Thread::BoostPriority(s32 priority) { current_priority = priority; } -SharedPtr SetupMainThread(u32 entry_point, s32 priority, SharedPtr owner_process) { +SharedPtr SetupMainThread(u32 entry_point, u32 priority, SharedPtr owner_process) { // Initialize new "main" thread auto thread_res = Thread::Create("main", entry_point, priority, 0, THREADPROCESSORID_0, Memory::HEAP_VADDR_END, owner_process); @@ -531,7 +531,7 @@ void Thread::SetWaitSynchronizationOutput(s32 output) { s32 Thread::GetWaitObjectIndex(WaitObject* object) const { ASSERT_MSG(!wait_objects.empty(), "Thread is not waiting for anything"); auto match = std::find(wait_objects.rbegin(), wait_objects.rend(), object); - return std::distance(match, wait_objects.rend()) - 1; + return static_cast(std::distance(match, wait_objects.rend()) - 1); } //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index ddc0d15c56..f02e1d43af 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -15,7 +15,7 @@ #include "core/hle/kernel/wait_object.h" #include "core/hle/result.h" -enum ThreadPriority : s32 { +enum ThreadPriority : u32 { THREADPRIO_HIGHEST = 0, ///< Highest thread priority THREADPRIO_USERLAND_MAX = 24, ///< Highest thread priority for userland apps THREADPRIO_DEFAULT = 48, ///< Default thread priority for userland apps @@ -82,7 +82,7 @@ public: * Gets the thread's current priority * @return The current thread's priority */ - s32 GetPriority() const { + u32 GetPriority() const { return current_priority; } @@ -90,7 +90,7 @@ public: * Sets the thread's current priority * @param priority The new priority */ - void SetPriority(s32 priority); + void SetPriority(u32 priority); /** * Boost's a thread's priority to the best priority among the thread's held mutexes. @@ -102,7 +102,7 @@ public: * Temporarily boosts the thread's priority until the next time it is scheduled * @param priority The new priority */ - void BoostPriority(s32 priority); + void BoostPriority(u32 priority); /** * Gets the thread's thread ID @@ -176,8 +176,8 @@ public: u32 entry_point; u32 stack_top; - s32 nominal_priority; ///< Nominal thread priority, as set by the emulated application - s32 current_priority; ///< Current thread priority, can be temporarily changed + u32 nominal_priority; ///< Nominal thread priority, as set by the emulated application + u32 current_priority; ///< Current thread priority, can be temporarily changed u64 last_running_ticks; ///< CPU tick when thread was last running @@ -219,7 +219,7 @@ private: * @param owner_process The parent process for the main thread * @return A shared pointer to the main thread */ -SharedPtr SetupMainThread(u32 entry_point, s32 priority, SharedPtr owner_process); +SharedPtr SetupMainThread(u32 entry_point, u32 priority, SharedPtr owner_process); /** * Returns whether there are any threads that are ready to run. diff --git a/src/core/hle/kernel/wait_object.cpp b/src/core/hle/kernel/wait_object.cpp index f245eda6cd..56fdd977fd 100644 --- a/src/core/hle/kernel/wait_object.cpp +++ b/src/core/hle/kernel/wait_object.cpp @@ -34,7 +34,7 @@ void WaitObject::RemoveWaitingThread(Thread* thread) { SharedPtr WaitObject::GetHighestPriorityReadyThread() { Thread* candidate = nullptr; - s32 candidate_priority = THREADPRIO_LOWEST + 1; + u32 candidate_priority = THREADPRIO_LOWEST + 1; for (const auto& thread : waiting_threads) { // The list of waiting threads must not contain threads that are not waiting to be awakened. diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index 8c0ba73f2a..4c61563456 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp @@ -561,7 +561,7 @@ void ReceiveParameter(Service::Interface* self) { ? Kernel::g_handle_table.Create(next_parameter->object).Unwrap() : 0); - rb.PushStaticBuffer(buffer, static_cast(next_parameter->buffer.size()), 0); + rb.PushStaticBuffer(buffer, next_parameter->buffer.size(), 0); Memory::WriteBlock(buffer, next_parameter->buffer.data(), next_parameter->buffer.size()); @@ -609,7 +609,7 @@ void GlanceParameter(Service::Interface* self) { ? Kernel::g_handle_table.Create(next_parameter->object).Unwrap() : 0); - rb.PushStaticBuffer(buffer, static_cast(next_parameter->buffer.size()), 0); + rb.PushStaticBuffer(buffer, next_parameter->buffer.size(), 0); Memory::WriteBlock(buffer, next_parameter->buffer.data(), next_parameter->buffer.size()); diff --git a/src/core/hle/service/cam/cam.cpp b/src/core/hle/service/cam/cam.cpp index c9f9e9d95b..8172edae89 100644 --- a/src/core/hle/service/cam/cam.cpp +++ b/src/core/hle/service/cam/cam.cpp @@ -177,7 +177,7 @@ void CompletionEventCallBack(u64 port_id, int) { LOG_ERROR(Service_CAM, "The destination size (%u) doesn't match the source (%zu)!", port.dest_size, buffer_size); } - Memory::WriteBlock(port.dest, buffer.data(), std::min(port.dest_size, buffer_size)); + Memory::WriteBlock(port.dest, buffer.data(), std::min(port.dest_size, buffer_size)); } port.is_receiving = false; diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp index f26a1f65fe..f78c25fb24 100644 --- a/src/core/hle/service/cfg/cfg.cpp +++ b/src/core/hle/service/cfg/cfg.cpp @@ -141,7 +141,7 @@ void GetCountryCodeString(Service::Interface* self) { void GetCountryCodeID(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); - u16 country_code = cmd_buff[1]; + u16 country_code = static_cast(cmd_buff[1]); u16 country_code_id = 0; // The following algorithm will fail if the first country code isn't 0. diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index 4ccb3cd32a..4ee7df73c7 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp @@ -217,7 +217,7 @@ void Directory::HandleSyncRequest(Kernel::SharedPtr serve LOG_TRACE(Service_FS, "Read %s: count=%d", GetName().c_str(), count); // Number of entries actually read - u32 read = backend->Read(entries.size(), entries.data()); + u32 read = backend->Read(static_cast(entries.size()), entries.data()); cmd_buff[2] = read; Memory::WriteBlock(address, entries.data(), read * sizeof(FileSys::Entry)); break; diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index aa5d821f92..379fbd71c1 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -251,7 +251,7 @@ static void UpdateGyroscopeCallback(u64 userdata, int cycles_late) { Math::Vec3 gyro; std::tie(std::ignore, gyro) = motion_device->GetStatus(); double stretch = Core::System::GetInstance().perf_stats.GetLastFrameTimeScale(); - gyro *= gyroscope_coef * stretch; + gyro *= gyroscope_coef * static_cast(stretch); gyroscope_entry.x = static_cast(gyro.x); gyroscope_entry.y = static_cast(gyro.y); gyroscope_entry.z = static_cast(gyro.z); diff --git a/src/core/hle/service/ldr_ro/cro_helper.h b/src/core/hle/service/ldr_ro/cro_helper.h index 3bc10dbdc0..57b4fb6df9 100644 --- a/src/core/hle/service/ldr_ro/cro_helper.h +++ b/src/core/hle/service/ldr_ro/cro_helper.h @@ -413,7 +413,8 @@ private: */ template void GetEntry(std::size_t index, T& data) const { - Memory::ReadBlock(GetField(T::TABLE_OFFSET_FIELD) + index * sizeof(T), &data, sizeof(T)); + Memory::ReadBlock(GetField(T::TABLE_OFFSET_FIELD) + static_cast(index * sizeof(T)), + &data, sizeof(T)); } /** @@ -425,7 +426,8 @@ private: */ template void SetEntry(std::size_t index, const T& data) { - Memory::WriteBlock(GetField(T::TABLE_OFFSET_FIELD) + index * sizeof(T), &data, sizeof(T)); + Memory::WriteBlock(GetField(T::TABLE_OFFSET_FIELD) + static_cast(index * sizeof(T)), + &data, sizeof(T)); } /** diff --git a/src/core/hle/service/nwm/nwm_uds.cpp b/src/core/hle/service/nwm/nwm_uds.cpp index 4e2af9ae67..8ef0cda091 100644 --- a/src/core/hle/service/nwm/nwm_uds.cpp +++ b/src/core/hle/service/nwm/nwm_uds.cpp @@ -316,7 +316,7 @@ static void RecvBeaconBroadcastData(Interface* self) { auto beacons = GetReceivedBeacons(mac_address); BeaconDataReplyHeader data_reply_header{}; - data_reply_header.total_entries = beacons.size(); + data_reply_header.total_entries = static_cast(beacons.size()); data_reply_header.max_output_size = out_buffer_size; Memory::WriteBlock(current_buffer_pos, &data_reply_header, sizeof(BeaconDataReplyHeader)); @@ -326,8 +326,8 @@ static void RecvBeaconBroadcastData(Interface* self) { for (const auto& beacon : beacons) { BeaconEntryHeader entry{}; // TODO(Subv): Figure out what this size is used for. - entry.unk_size = sizeof(BeaconEntryHeader) + beacon.data.size(); - entry.total_size = sizeof(BeaconEntryHeader) + beacon.data.size(); + entry.unk_size = static_cast(sizeof(BeaconEntryHeader) + beacon.data.size()); + entry.total_size = static_cast(sizeof(BeaconEntryHeader) + beacon.data.size()); entry.wifi_channel = beacon.channel; entry.header_size = sizeof(BeaconEntryHeader); entry.mac_address = beacon.transmitter_address; @@ -338,9 +338,9 @@ static void RecvBeaconBroadcastData(Interface* self) { current_buffer_pos += sizeof(BeaconEntryHeader); Memory::WriteBlock(current_buffer_pos, beacon.data.data(), beacon.data.size()); - current_buffer_pos += beacon.data.size(); + current_buffer_pos += static_cast(beacon.data.size()); - total_size += sizeof(BeaconEntryHeader) + beacon.data.size(); + total_size += static_cast(sizeof(BeaconEntryHeader) + beacon.data.size()); } // Update the total size in the structure and write it to the buffer again. diff --git a/src/core/hle/service/nwm/uds_beacon.cpp b/src/core/hle/service/nwm/uds_beacon.cpp index 552eaf65ec..73a80d940f 100644 --- a/src/core/hle/service/nwm/uds_beacon.cpp +++ b/src/core/hle/service/nwm/uds_beacon.cpp @@ -243,7 +243,7 @@ std::vector GenerateNintendoFirstEncryptedDataTag(const NetworkInfo& network EncryptedDataTag tag{}; tag.header.tag_id = static_cast(TagId::VendorSpecific); - tag.header.length = sizeof(tag) - sizeof(TagHeader) + payload_size; + tag.header.length = static_cast(sizeof(tag) - sizeof(TagHeader) + payload_size); tag.oui_type = static_cast(NintendoTagId::EncryptedData0); tag.oui = NintendoOUI; @@ -279,7 +279,7 @@ std::vector GenerateNintendoSecondEncryptedDataTag(const NetworkInfo& networ EncryptedDataTag tag{}; tag.header.tag_id = static_cast(TagId::VendorSpecific); - tag.header.length = tag_length; + tag.header.length = static_cast(tag_length); tag.oui_type = static_cast(NintendoTagId::EncryptedData1); tag.oui = NintendoOUI; diff --git a/src/core/hle/service/nwm/uds_data.cpp b/src/core/hle/service/nwm/uds_data.cpp index 0fd9b8b8c6..3ef2a84b63 100644 --- a/src/core/hle/service/nwm/uds_data.cpp +++ b/src/core/hle/service/nwm/uds_data.cpp @@ -197,7 +197,7 @@ static std::vector DecryptDataFrame(const std::vector& encrypted_payload df.ChannelMessageEnd(CryptoPP::DEFAULT_CHANNEL); df.SetRetrievalChannel(CryptoPP::DEFAULT_CHANNEL); - int size = df.MaxRetrievable(); + size_t size = df.MaxRetrievable(); std::vector pdata(size); df.Get(pdata.data(), size); @@ -251,7 +251,7 @@ static std::vector EncryptDataFrame(const std::vector& payload, df.SetRetrievalChannel(CryptoPP::DEFAULT_CHANNEL); - int size = df.MaxRetrievable(); + size_t size = df.MaxRetrievable(); std::vector cipher(size); df.Get(cipher.data(), size); @@ -266,8 +266,8 @@ static std::vector EncryptDataFrame(const std::vector& payload, std::vector GenerateDataPayload(const std::vector& data, u8 channel, u16 dest_node, u16 src_node, u16 sequence_number) { std::vector buffer = GenerateLLCHeader(EtherType::SecureData); - std::vector securedata_header = - GenerateSecureDataHeader(data.size(), channel, dest_node, src_node, sequence_number); + std::vector securedata_header = GenerateSecureDataHeader( + static_cast(data.size()), channel, dest_node, src_node, sequence_number); buffer.insert(buffer.end(), securedata_header.begin(), securedata_header.end()); buffer.insert(buffer.end(), data.begin(), data.end()); diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 05c6897bf8..41c82c9226 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -361,7 +361,7 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha // We found a ready object, acquire it and set the result value Kernel::WaitObject* object = itr->get(); object->Acquire(thread); - *out = std::distance(objects.begin(), itr); + *out = static_cast(std::distance(objects.begin(), itr)); return RESULT_SUCCESS; } @@ -469,7 +469,7 @@ static ResultCode ReplyAndReceive(s32* index, Kernel::Handle* handles, s32 handl // We found a ready object, acquire it and set the result value Kernel::WaitObject* object = itr->get(); object->Acquire(thread); - *index = std::distance(objects.begin(), itr); + *index = static_cast(std::distance(objects.begin(), itr)); if (object->GetHandleType() == Kernel::HandleType::ServerSession) { auto server_session = static_cast(object); @@ -683,7 +683,7 @@ static void ExitThread() { } /// Gets the priority for the specified thread -static ResultCode GetThreadPriority(s32* priority, Kernel::Handle handle) { +static ResultCode GetThreadPriority(u32* priority, Kernel::Handle handle) { const SharedPtr thread = Kernel::g_handle_table.Get(handle); if (thread == nullptr) return ERR_INVALID_HANDLE; @@ -693,7 +693,7 @@ static ResultCode GetThreadPriority(s32* priority, Kernel::Handle handle) { } /// Sets the priority for the specified thread -static ResultCode SetThreadPriority(Kernel::Handle handle, s32 priority) { +static ResultCode SetThreadPriority(Kernel::Handle handle, u32 priority) { if (priority > THREADPRIO_LOWEST) { return Kernel::ERR_OUT_OF_RANGE; } diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 5ea0694a97..847e697106 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -477,7 +477,7 @@ void ReadBlock(const VAddr src_addr, void* dest_buffer, const size_t size) { while (remaining_size > 0) { const size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size); - const VAddr current_vaddr = (page_index << PAGE_BITS) + page_offset; + const VAddr current_vaddr = static_cast((page_index << PAGE_BITS) + page_offset); switch (current_page_table->attributes[page_index]) { case PageType::Unmapped: { @@ -500,13 +500,15 @@ void ReadBlock(const VAddr src_addr, void* dest_buffer, const size_t size) { break; } case PageType::RasterizerCachedMemory: { - RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::Flush); + RasterizerFlushVirtualRegion(current_vaddr, static_cast(copy_amount), + FlushMode::Flush); std::memcpy(dest_buffer, GetPointerFromVMA(current_vaddr), copy_amount); break; } case PageType::RasterizerCachedSpecial: { DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); - RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::Flush); + RasterizerFlushVirtualRegion(current_vaddr, static_cast(copy_amount), + FlushMode::Flush); GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, dest_buffer, copy_amount); break; } @@ -544,7 +546,7 @@ void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size while (remaining_size > 0) { const size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size); - const VAddr current_vaddr = (page_index << PAGE_BITS) + page_offset; + const VAddr current_vaddr = static_cast((page_index << PAGE_BITS) + page_offset); switch (current_page_table->attributes[page_index]) { case PageType::Unmapped: { @@ -567,13 +569,15 @@ void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size break; } case PageType::RasterizerCachedMemory: { - RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::FlushAndInvalidate); + RasterizerFlushVirtualRegion(current_vaddr, static_cast(copy_amount), + FlushMode::FlushAndInvalidate); std::memcpy(GetPointerFromVMA(current_vaddr), src_buffer, copy_amount); break; } case PageType::RasterizerCachedSpecial: { DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); - RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::FlushAndInvalidate); + RasterizerFlushVirtualRegion(current_vaddr, static_cast(copy_amount), + FlushMode::FlushAndInvalidate); GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, src_buffer, copy_amount); break; } @@ -597,7 +601,7 @@ void ZeroBlock(const VAddr dest_addr, const size_t size) { while (remaining_size > 0) { const size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size); - const VAddr current_vaddr = (page_index << PAGE_BITS) + page_offset; + const VAddr current_vaddr = static_cast((page_index << PAGE_BITS) + page_offset); switch (current_page_table->attributes[page_index]) { case PageType::Unmapped: { @@ -619,13 +623,15 @@ void ZeroBlock(const VAddr dest_addr, const size_t size) { break; } case PageType::RasterizerCachedMemory: { - RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::FlushAndInvalidate); + RasterizerFlushVirtualRegion(current_vaddr, static_cast(copy_amount), + FlushMode::FlushAndInvalidate); std::memset(GetPointerFromVMA(current_vaddr), 0, copy_amount); break; } case PageType::RasterizerCachedSpecial: { DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); - RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::FlushAndInvalidate); + RasterizerFlushVirtualRegion(current_vaddr, static_cast(copy_amount), + FlushMode::FlushAndInvalidate); GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, zeros.data(), copy_amount); break; } @@ -646,7 +652,7 @@ void CopyBlock(VAddr dest_addr, VAddr src_addr, const size_t size) { while (remaining_size > 0) { const size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size); - const VAddr current_vaddr = (page_index << PAGE_BITS) + page_offset; + const VAddr current_vaddr = static_cast((page_index << PAGE_BITS) + page_offset); switch (current_page_table->attributes[page_index]) { case PageType::Unmapped: { @@ -670,13 +676,15 @@ void CopyBlock(VAddr dest_addr, VAddr src_addr, const size_t size) { break; } case PageType::RasterizerCachedMemory: { - RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::Flush); + RasterizerFlushVirtualRegion(current_vaddr, static_cast(copy_amount), + FlushMode::Flush); WriteBlock(dest_addr, GetPointerFromVMA(current_vaddr), copy_amount); break; } case PageType::RasterizerCachedSpecial: { DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); - RasterizerFlushVirtualRegion(current_vaddr, copy_amount, FlushMode::Flush); + RasterizerFlushVirtualRegion(current_vaddr, static_cast(copy_amount), + FlushMode::Flush); std::vector buffer(copy_amount); GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, buffer.data(), buffer.size()); @@ -689,8 +697,8 @@ void CopyBlock(VAddr dest_addr, VAddr src_addr, const size_t size) { page_index++; page_offset = 0; - dest_addr += copy_amount; - src_addr += copy_amount; + dest_addr += static_cast(copy_amount); + src_addr += static_cast(copy_amount); remaining_size -= copy_amount; } } diff --git a/src/network/packet.cpp b/src/network/packet.cpp index cc60f2fbca..7e1a812f34 100644 --- a/src/network/packet.cpp +++ b/src/network/packet.cpp @@ -233,7 +233,7 @@ Packet& Packet::operator<<(double in_data) { Packet& Packet::operator<<(const char* in_data) { // First insert string length - u32 length = std::strlen(in_data); + u32 length = static_cast(std::strlen(in_data)); *this << length; // Then insert characters diff --git a/src/video_core/geometry_pipeline.cpp b/src/video_core/geometry_pipeline.cpp index b146e2ecb1..98ff2ccd38 100644 --- a/src/video_core/geometry_pipeline.cpp +++ b/src/video_core/geometry_pipeline.cpp @@ -105,7 +105,7 @@ public: DEBUG_ASSERT(need_index); // The number of vertex input is put to the uniform register - float24 vertex_num = float24::FromFloat32(val); + float24 vertex_num = float24::FromFloat32(static_cast(val)); setup.uniforms.f[0] = Math::MakeVec(vertex_num, vertex_num, vertex_num, vertex_num); // The second uniform register and so on are used for receiving input vertices diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index 06a905766f..5770ae08f2 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp @@ -267,9 +267,9 @@ void OpenGLState::Apply() const { for (size_t i = 0; i < clip_distance.size(); ++i) { if (clip_distance[i] != cur_state.clip_distance[i]) { if (clip_distance[i]) { - glEnable(GL_CLIP_DISTANCE0 + i); + glEnable(GL_CLIP_DISTANCE0 + static_cast(i)); } else { - glDisable(GL_CLIP_DISTANCE0 + i); + glDisable(GL_CLIP_DISTANCE0 + static_cast(i)); } } } -- cgit v1.2.3 From 141da6b66761cfcd82b685d4702af196b39be24d Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 29 Sep 2017 14:47:52 -0500 Subject: Kernel/Thread: Added a helper function to get a thread's command buffer VAddr. --- src/core/hle/kernel/thread.cpp | 6 ++++++ src/core/hle/kernel/thread.h | 6 ++++++ 2 files changed, 12 insertions(+) (limited to 'src/core/hle/kernel/thread.cpp') diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 11f7d21277..6ebc8c151c 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -534,6 +534,12 @@ s32 Thread::GetWaitObjectIndex(WaitObject* object) const { return static_cast(std::distance(match, wait_objects.rend()) - 1); } +VAddr Thread::GetCommandBufferAddress() const { + // Offset from the start of TLS at which the IPC command buffer begins. + static constexpr int CommandHeaderOffset = 0x80; + return GetTLSAddress() + CommandHeaderOffset; +} + //////////////////////////////////////////////////////////////////////////////////////////////////// void ThreadingInit() { diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index f02e1d43af..520ac22c2c 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -159,6 +159,12 @@ public: return tls_address; } + /* + * Returns the address of the current thread's command buffer, located in the TLS. + * @returns VAddr of the thread's command buffer. + */ + VAddr GetCommandBufferAddress() const; + /** * Returns whether this thread is waiting for all the objects in * its wait list to become ready, as a result of a WaitSynchronizationN call -- cgit v1.2.3