Merge pull request #1956 from lioncash/process-thread
kernel/process: Start the main thread using the specified ideal core
This commit is contained in:
		
						commit
						e5dfbe22ee
					
				@ -20,6 +20,35 @@
 | 
			
		||||
#include "core/settings.h"
 | 
			
		||||
 | 
			
		||||
namespace Kernel {
 | 
			
		||||
namespace {
 | 
			
		||||
/**
 | 
			
		||||
 * Sets up the primary application thread
 | 
			
		||||
 *
 | 
			
		||||
 * @param owner_process The parent process for the main thread
 | 
			
		||||
 * @param kernel The kernel instance to create the main thread under.
 | 
			
		||||
 * @param entry_point The address at which the thread should start execution
 | 
			
		||||
 * @param priority The priority to give the main thread
 | 
			
		||||
 */
 | 
			
		||||
void SetupMainThread(Process& owner_process, KernelCore& kernel, VAddr entry_point, u32 priority) {
 | 
			
		||||
    // Setup page table so we can write to memory
 | 
			
		||||
    SetCurrentPageTable(&owner_process.VMManager().page_table);
 | 
			
		||||
 | 
			
		||||
    // Initialize new "main" thread
 | 
			
		||||
    const VAddr stack_top = owner_process.VMManager().GetTLSIORegionEndAddress();
 | 
			
		||||
    auto thread_res = Thread::Create(kernel, "main", entry_point, priority, 0,
 | 
			
		||||
                                     owner_process.GetIdealCore(), stack_top, owner_process);
 | 
			
		||||
 | 
			
		||||
    SharedPtr<Thread> thread = std::move(thread_res).Unwrap();
 | 
			
		||||
 | 
			
		||||
    // Register 1 must be a handle to the main thread
 | 
			
		||||
    const Handle guest_handle = owner_process.GetHandleTable().Create(thread).Unwrap();
 | 
			
		||||
    thread->SetGuestHandle(guest_handle);
 | 
			
		||||
    thread->GetContext().cpu_registers[1] = guest_handle;
 | 
			
		||||
 | 
			
		||||
    // Threads by default are dormant, wake up the main thread so it runs when the scheduler fires
 | 
			
		||||
    thread->ResumeFromWait();
 | 
			
		||||
}
 | 
			
		||||
} // Anonymous namespace
 | 
			
		||||
 | 
			
		||||
CodeSet::CodeSet() = default;
 | 
			
		||||
CodeSet::~CodeSet() = default;
 | 
			
		||||
@ -64,7 +93,7 @@ ResultCode Process::ClearSignalState() {
 | 
			
		||||
 | 
			
		||||
ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) {
 | 
			
		||||
    program_id = metadata.GetTitleID();
 | 
			
		||||
    ideal_processor = metadata.GetMainThreadCore();
 | 
			
		||||
    ideal_core = metadata.GetMainThreadCore();
 | 
			
		||||
    is_64bit_process = metadata.Is64BitProgram();
 | 
			
		||||
 | 
			
		||||
    vm_manager.Reset(metadata.GetAddressSpaceType());
 | 
			
		||||
@ -86,7 +115,7 @@ void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) {
 | 
			
		||||
    vm_manager.LogLayout();
 | 
			
		||||
    ChangeStatus(ProcessStatus::Running);
 | 
			
		||||
 | 
			
		||||
    Kernel::SetupMainThread(kernel, entry_point, main_thread_priority, *this);
 | 
			
		||||
    SetupMainThread(*this, kernel, entry_point, main_thread_priority);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Process::PrepareForTermination() {
 | 
			
		||||
 | 
			
		||||
@ -168,9 +168,9 @@ public:
 | 
			
		||||
    /// Gets the resource limit descriptor for this process
 | 
			
		||||
    SharedPtr<ResourceLimit> GetResourceLimit() const;
 | 
			
		||||
 | 
			
		||||
    /// Gets the default CPU ID for this process
 | 
			
		||||
    u8 GetDefaultProcessorID() const {
 | 
			
		||||
        return ideal_processor;
 | 
			
		||||
    /// Gets the ideal CPU core ID for this process
 | 
			
		||||
    u8 GetIdealCore() const {
 | 
			
		||||
        return ideal_core;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Gets the bitmask of allowed CPUs that this process' threads can run on.
 | 
			
		||||
@ -280,8 +280,8 @@ private:
 | 
			
		||||
    /// Resource limit descriptor for this process
 | 
			
		||||
    SharedPtr<ResourceLimit> resource_limit;
 | 
			
		||||
 | 
			
		||||
    /// The default CPU for this process, threads are scheduled on this cpu by default.
 | 
			
		||||
    u8 ideal_processor = 0;
 | 
			
		||||
    /// The ideal CPU core for this process, threads are scheduled on this core by default.
 | 
			
		||||
    u8 ideal_core = 0;
 | 
			
		||||
    u32 is_virtual_address_memory_enabled = 0;
 | 
			
		||||
 | 
			
		||||
    /// The Thread Local Storage area is allocated as processes create threads,
 | 
			
		||||
 | 
			
		||||
@ -1227,10 +1227,10 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
 | 
			
		||||
 | 
			
		||||
    auto* const current_process = Core::CurrentProcess();
 | 
			
		||||
 | 
			
		||||
    if (processor_id == THREADPROCESSORID_DEFAULT) {
 | 
			
		||||
        // Set the target CPU to the one specified in the process' exheader.
 | 
			
		||||
        processor_id = current_process->GetDefaultProcessorID();
 | 
			
		||||
        ASSERT(processor_id != THREADPROCESSORID_DEFAULT);
 | 
			
		||||
    if (processor_id == THREADPROCESSORID_IDEAL) {
 | 
			
		||||
        // Set the target CPU to the one specified by the process.
 | 
			
		||||
        processor_id = current_process->GetIdealCore();
 | 
			
		||||
        ASSERT(processor_id != THREADPROCESSORID_IDEAL);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    switch (processor_id) {
 | 
			
		||||
@ -1639,13 +1639,13 @@ static ResultCode SetThreadCoreMask(Handle thread_handle, u32 core, u64 mask) {
 | 
			
		||||
        return ERR_INVALID_HANDLE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (core == static_cast<u32>(THREADPROCESSORID_DEFAULT)) {
 | 
			
		||||
        const u8 default_processor_id = thread->GetOwnerProcess()->GetDefaultProcessorID();
 | 
			
		||||
    if (core == static_cast<u32>(THREADPROCESSORID_IDEAL)) {
 | 
			
		||||
        const u8 ideal_cpu_core = thread->GetOwnerProcess()->GetIdealCore();
 | 
			
		||||
 | 
			
		||||
        ASSERT(default_processor_id != static_cast<u8>(THREADPROCESSORID_DEFAULT));
 | 
			
		||||
        ASSERT(ideal_cpu_core != static_cast<u8>(THREADPROCESSORID_IDEAL));
 | 
			
		||||
 | 
			
		||||
        // Set the target CPU to the one specified in the process' exheader.
 | 
			
		||||
        core = default_processor_id;
 | 
			
		||||
        // Set the target CPU to the ideal core specified by the process.
 | 
			
		||||
        core = ideal_cpu_core;
 | 
			
		||||
        mask = 1ULL << core;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -12,7 +12,6 @@
 | 
			
		||||
#include "common/assert.h"
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "common/logging/log.h"
 | 
			
		||||
#include "common/math_util.h"
 | 
			
		||||
#include "common/thread_queue_list.h"
 | 
			
		||||
#include "core/arm/arm_interface.h"
 | 
			
		||||
#include "core/core.h"
 | 
			
		||||
@ -232,29 +231,6 @@ void Thread::BoostPriority(u32 priority) {
 | 
			
		||||
    current_priority = priority;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SharedPtr<Thread> SetupMainThread(KernelCore& kernel, VAddr entry_point, u32 priority,
 | 
			
		||||
                                  Process& owner_process) {
 | 
			
		||||
    // Setup page table so we can write to memory
 | 
			
		||||
    SetCurrentPageTable(&owner_process.VMManager().page_table);
 | 
			
		||||
 | 
			
		||||
    // Initialize new "main" thread
 | 
			
		||||
    const VAddr stack_top = owner_process.VMManager().GetTLSIORegionEndAddress();
 | 
			
		||||
    auto thread_res = Thread::Create(kernel, "main", entry_point, priority, 0, THREADPROCESSORID_0,
 | 
			
		||||
                                     stack_top, owner_process);
 | 
			
		||||
 | 
			
		||||
    SharedPtr<Thread> thread = std::move(thread_res).Unwrap();
 | 
			
		||||
 | 
			
		||||
    // Register 1 must be a handle to the main thread
 | 
			
		||||
    const Handle guest_handle = owner_process.GetHandleTable().Create(thread).Unwrap();
 | 
			
		||||
    thread->SetGuestHandle(guest_handle);
 | 
			
		||||
    thread->GetContext().cpu_registers[1] = guest_handle;
 | 
			
		||||
 | 
			
		||||
    // Threads by default are dormant, wake up the main thread so it runs when the scheduler fires
 | 
			
		||||
    thread->ResumeFromWait();
 | 
			
		||||
 | 
			
		||||
    return thread;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Thread::SetWaitSynchronizationResult(ResultCode result) {
 | 
			
		||||
    context.cpu_registers[0] = result.raw;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -30,7 +30,7 @@ enum ThreadPriority : u32 {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum ThreadProcessorId : s32 {
 | 
			
		||||
    THREADPROCESSORID_DEFAULT = -2, ///< Run thread on default core specified by exheader
 | 
			
		||||
    THREADPROCESSORID_IDEAL = -2, ///< Run thread on the ideal core specified by the process.
 | 
			
		||||
    THREADPROCESSORID_0 = 0,      ///< Run thread on core 0
 | 
			
		||||
    THREADPROCESSORID_1 = 1,      ///< Run thread on core 1
 | 
			
		||||
    THREADPROCESSORID_2 = 2,      ///< Run thread on core 2
 | 
			
		||||
@ -455,17 +455,6 @@ private:
 | 
			
		||||
    ThreadActivity activity = ThreadActivity::Normal;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Sets up the primary application thread
 | 
			
		||||
 * @param kernel The kernel instance to create the main thread under.
 | 
			
		||||
 * @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<Thread> SetupMainThread(KernelCore& kernel, VAddr entry_point, u32 priority,
 | 
			
		||||
                                  Process& owner_process);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Gets the current thread
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@ -293,8 +293,8 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const {
 | 
			
		||||
 | 
			
		||||
    QString processor;
 | 
			
		||||
    switch (thread.GetProcessorID()) {
 | 
			
		||||
    case Kernel::ThreadProcessorId::THREADPROCESSORID_DEFAULT:
 | 
			
		||||
        processor = tr("default");
 | 
			
		||||
    case Kernel::ThreadProcessorId::THREADPROCESSORID_IDEAL:
 | 
			
		||||
        processor = tr("ideal");
 | 
			
		||||
        break;
 | 
			
		||||
    case Kernel::ThreadProcessorId::THREADPROCESSORID_0:
 | 
			
		||||
    case Kernel::ThreadProcessorId::THREADPROCESSORID_1:
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user