mirror of
https://github.com/citra-emu/citra.git
synced 2024-12-18 12:10:04 +00:00
Merge pull request #3301 from Subv/exitprocess2
Kernel/SVC: Partially implemented svcExitProcess.
This commit is contained in:
commit
c3c684cd2b
@ -40,6 +40,7 @@ SharedPtr<Process> Process::Create(SharedPtr<CodeSet> code_set) {
|
|||||||
process->codeset = std::move(code_set);
|
process->codeset = std::move(code_set);
|
||||||
process->flags.raw = 0;
|
process->flags.raw = 0;
|
||||||
process->flags.memory_region.Assign(MemoryRegion::APPLICATION);
|
process->flags.memory_region.Assign(MemoryRegion::APPLICATION);
|
||||||
|
process->status = ProcessStatus::Created;
|
||||||
|
|
||||||
process_list.push_back(process);
|
process_list.push_back(process);
|
||||||
return process;
|
return process;
|
||||||
@ -151,6 +152,8 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) {
|
|||||||
HandleSpecialMapping(vm_manager, mapping);
|
HandleSpecialMapping(vm_manager, mapping);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status = ProcessStatus::Running;
|
||||||
|
|
||||||
vm_manager.LogLayout(Log::Level::Debug);
|
vm_manager.LogLayout(Log::Level::Debug);
|
||||||
Kernel::SetupMainThread(codeset->entrypoint, main_thread_priority, this);
|
Kernel::SetupMainThread(codeset->entrypoint, main_thread_priority, this);
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,8 @@ union ProcessFlags {
|
|||||||
BitField<12, 1, u16> loaded_high; ///< Application loaded high (not at 0x00100000).
|
BitField<12, 1, u16> loaded_high; ///< Application loaded high (not at 0x00100000).
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class ProcessStatus { Created, Running, Exited };
|
||||||
|
|
||||||
class ResourceLimit;
|
class ResourceLimit;
|
||||||
struct MemoryRegionInfo;
|
struct MemoryRegionInfo;
|
||||||
|
|
||||||
@ -122,6 +124,8 @@ public:
|
|||||||
u16 kernel_version = 0;
|
u16 kernel_version = 0;
|
||||||
/// The default CPU for this process, threads are scheduled on this cpu by default.
|
/// The default CPU for this process, threads are scheduled on this cpu by default.
|
||||||
u8 ideal_processor = 0;
|
u8 ideal_processor = 0;
|
||||||
|
/// Current status of the process
|
||||||
|
ProcessStatus status;
|
||||||
|
|
||||||
/// The id of this process
|
/// The id of this process
|
||||||
u32 process_id = next_process_id++;
|
u32 process_id = next_process_id++;
|
||||||
|
@ -143,6 +143,36 @@ static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 add
|
|||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ExitProcess() {
|
||||||
|
LOG_INFO(Kernel_SVC, "Process %u exiting", g_current_process->process_id);
|
||||||
|
|
||||||
|
ASSERT_MSG(g_current_process->status == ProcessStatus::Running, "Process has already exited");
|
||||||
|
|
||||||
|
g_current_process->status = ProcessStatus::Exited;
|
||||||
|
|
||||||
|
// Stop all the process threads that are currently waiting for objects.
|
||||||
|
auto& thread_list = GetThreadList();
|
||||||
|
for (auto& thread : thread_list) {
|
||||||
|
if (thread->owner_process != g_current_process)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (thread == GetCurrentThread())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// TODO(Subv): When are the other running/ready threads terminated?
|
||||||
|
ASSERT_MSG(thread->status == THREADSTATUS_WAIT_SYNCH_ANY ||
|
||||||
|
thread->status == THREADSTATUS_WAIT_SYNCH_ALL,
|
||||||
|
"Exiting processes with non-waiting threads is currently unimplemented");
|
||||||
|
|
||||||
|
thread->Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kill the current thread
|
||||||
|
GetCurrentThread()->Stop();
|
||||||
|
|
||||||
|
Core::System::GetInstance().PrepareReschedule();
|
||||||
|
}
|
||||||
|
|
||||||
/// Maps a memory block to specified address
|
/// Maps a memory block to specified address
|
||||||
static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other_permissions) {
|
static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other_permissions) {
|
||||||
LOG_TRACE(Kernel_SVC,
|
LOG_TRACE(Kernel_SVC,
|
||||||
@ -1232,7 +1262,7 @@ static const FunctionDef SVC_Table[] = {
|
|||||||
{0x00, nullptr, "Unknown"},
|
{0x00, nullptr, "Unknown"},
|
||||||
{0x01, HLE::Wrap<ControlMemory>, "ControlMemory"},
|
{0x01, HLE::Wrap<ControlMemory>, "ControlMemory"},
|
||||||
{0x02, HLE::Wrap<QueryMemory>, "QueryMemory"},
|
{0x02, HLE::Wrap<QueryMemory>, "QueryMemory"},
|
||||||
{0x03, nullptr, "ExitProcess"},
|
{0x03, ExitProcess, "ExitProcess"},
|
||||||
{0x04, nullptr, "GetProcessAffinityMask"},
|
{0x04, nullptr, "GetProcessAffinityMask"},
|
||||||
{0x05, nullptr, "SetProcessAffinityMask"},
|
{0x05, nullptr, "SetProcessAffinityMask"},
|
||||||
{0x06, nullptr, "GetProcessIdealProcessor"},
|
{0x06, nullptr, "GetProcessIdealProcessor"},
|
||||||
@ -1373,6 +1403,9 @@ void CallSVC(u32 immediate) {
|
|||||||
// Lock the global kernel mutex when we enter the kernel HLE.
|
// Lock the global kernel mutex when we enter the kernel HLE.
|
||||||
std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock);
|
std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock);
|
||||||
|
|
||||||
|
ASSERT_MSG(g_current_process->status == ProcessStatus::Running,
|
||||||
|
"Running threads from exiting processes is unimplemented");
|
||||||
|
|
||||||
const FunctionDef* info = GetSVCInfo(immediate);
|
const FunctionDef* info = GetSVCInfo(immediate);
|
||||||
if (info) {
|
if (info) {
|
||||||
if (info->func) {
|
if (info->func) {
|
||||||
|
Loading…
Reference in New Issue
Block a user