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"
|
#include "core/settings.h"
|
||||||
|
|
||||||
namespace Kernel {
|
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;
|
||||||
CodeSet::~CodeSet() = default;
|
CodeSet::~CodeSet() = default;
|
||||||
|
@ -64,7 +93,7 @@ ResultCode Process::ClearSignalState() {
|
||||||
|
|
||||||
ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) {
|
ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) {
|
||||||
program_id = metadata.GetTitleID();
|
program_id = metadata.GetTitleID();
|
||||||
ideal_processor = metadata.GetMainThreadCore();
|
ideal_core = metadata.GetMainThreadCore();
|
||||||
is_64bit_process = metadata.Is64BitProgram();
|
is_64bit_process = metadata.Is64BitProgram();
|
||||||
|
|
||||||
vm_manager.Reset(metadata.GetAddressSpaceType());
|
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();
|
vm_manager.LogLayout();
|
||||||
ChangeStatus(ProcessStatus::Running);
|
ChangeStatus(ProcessStatus::Running);
|
||||||
|
|
||||||
Kernel::SetupMainThread(kernel, entry_point, main_thread_priority, *this);
|
SetupMainThread(*this, kernel, entry_point, main_thread_priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process::PrepareForTermination() {
|
void Process::PrepareForTermination() {
|
||||||
|
|
|
@ -168,9 +168,9 @@ public:
|
||||||
/// Gets the resource limit descriptor for this process
|
/// Gets the resource limit descriptor for this process
|
||||||
SharedPtr<ResourceLimit> GetResourceLimit() const;
|
SharedPtr<ResourceLimit> GetResourceLimit() const;
|
||||||
|
|
||||||
/// Gets the default CPU ID for this process
|
/// Gets the ideal CPU core ID for this process
|
||||||
u8 GetDefaultProcessorID() const {
|
u8 GetIdealCore() const {
|
||||||
return ideal_processor;
|
return ideal_core;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the bitmask of allowed CPUs that this process' threads can run on.
|
/// Gets the bitmask of allowed CPUs that this process' threads can run on.
|
||||||
|
@ -280,8 +280,8 @@ private:
|
||||||
/// Resource limit descriptor for this process
|
/// Resource limit descriptor for this process
|
||||||
SharedPtr<ResourceLimit> resource_limit;
|
SharedPtr<ResourceLimit> resource_limit;
|
||||||
|
|
||||||
/// The default CPU for this process, threads are scheduled on this cpu by default.
|
/// The ideal CPU core for this process, threads are scheduled on this core by default.
|
||||||
u8 ideal_processor = 0;
|
u8 ideal_core = 0;
|
||||||
u32 is_virtual_address_memory_enabled = 0;
|
u32 is_virtual_address_memory_enabled = 0;
|
||||||
|
|
||||||
/// The Thread Local Storage area is allocated as processes create threads,
|
/// 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();
|
auto* const current_process = Core::CurrentProcess();
|
||||||
|
|
||||||
if (processor_id == THREADPROCESSORID_DEFAULT) {
|
if (processor_id == THREADPROCESSORID_IDEAL) {
|
||||||
// Set the target CPU to the one specified in the process' exheader.
|
// Set the target CPU to the one specified by the process.
|
||||||
processor_id = current_process->GetDefaultProcessorID();
|
processor_id = current_process->GetIdealCore();
|
||||||
ASSERT(processor_id != THREADPROCESSORID_DEFAULT);
|
ASSERT(processor_id != THREADPROCESSORID_IDEAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (processor_id) {
|
switch (processor_id) {
|
||||||
|
@ -1639,13 +1639,13 @@ static ResultCode SetThreadCoreMask(Handle thread_handle, u32 core, u64 mask) {
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (core == static_cast<u32>(THREADPROCESSORID_DEFAULT)) {
|
if (core == static_cast<u32>(THREADPROCESSORID_IDEAL)) {
|
||||||
const u8 default_processor_id = thread->GetOwnerProcess()->GetDefaultProcessorID();
|
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.
|
// Set the target CPU to the ideal core specified by the process.
|
||||||
core = default_processor_id;
|
core = ideal_cpu_core;
|
||||||
mask = 1ULL << core;
|
mask = 1ULL << core;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/math_util.h"
|
|
||||||
#include "common/thread_queue_list.h"
|
#include "common/thread_queue_list.h"
|
||||||
#include "core/arm/arm_interface.h"
|
#include "core/arm/arm_interface.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
|
@ -232,29 +231,6 @@ void Thread::BoostPriority(u32 priority) {
|
||||||
current_priority = 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) {
|
void Thread::SetWaitSynchronizationResult(ResultCode result) {
|
||||||
context.cpu_registers[0] = result.raw;
|
context.cpu_registers[0] = result.raw;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,12 +30,12 @@ enum ThreadPriority : u32 {
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ThreadProcessorId : s32 {
|
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_0 = 0, ///< Run thread on core 0
|
||||||
THREADPROCESSORID_1 = 1, ///< Run thread on core 1
|
THREADPROCESSORID_1 = 1, ///< Run thread on core 1
|
||||||
THREADPROCESSORID_2 = 2, ///< Run thread on core 2
|
THREADPROCESSORID_2 = 2, ///< Run thread on core 2
|
||||||
THREADPROCESSORID_3 = 3, ///< Run thread on core 3
|
THREADPROCESSORID_3 = 3, ///< Run thread on core 3
|
||||||
THREADPROCESSORID_MAX = 4, ///< Processor ID must be less than this
|
THREADPROCESSORID_MAX = 4, ///< Processor ID must be less than this
|
||||||
|
|
||||||
/// Allowed CPU mask
|
/// Allowed CPU mask
|
||||||
THREADPROCESSORID_DEFAULT_MASK = (1 << THREADPROCESSORID_0) | (1 << THREADPROCESSORID_1) |
|
THREADPROCESSORID_DEFAULT_MASK = (1 << THREADPROCESSORID_0) | (1 << THREADPROCESSORID_1) |
|
||||||
|
@ -455,17 +455,6 @@ private:
|
||||||
ThreadActivity activity = ThreadActivity::Normal;
|
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
|
* Gets the current thread
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -293,8 +293,8 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const {
|
||||||
|
|
||||||
QString processor;
|
QString processor;
|
||||||
switch (thread.GetProcessorID()) {
|
switch (thread.GetProcessorID()) {
|
||||||
case Kernel::ThreadProcessorId::THREADPROCESSORID_DEFAULT:
|
case Kernel::ThreadProcessorId::THREADPROCESSORID_IDEAL:
|
||||||
processor = tr("default");
|
processor = tr("ideal");
|
||||||
break;
|
break;
|
||||||
case Kernel::ThreadProcessorId::THREADPROCESSORID_0:
|
case Kernel::ThreadProcessorId::THREADPROCESSORID_0:
|
||||||
case Kernel::ThreadProcessorId::THREADPROCESSORID_1:
|
case Kernel::ThreadProcessorId::THREADPROCESSORID_1:
|
||||||
|
|
Reference in New Issue