svc: Implement svcExitProcess.

This commit is contained in:
bunnei 2018-01-01 14:38:34 -05:00
parent 9b8afed5f7
commit aa7c824ea4
3 changed files with 77 additions and 11 deletions

View File

@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <algorithm>
#include <memory> #include <memory>
#include "common/assert.h" #include "common/assert.h"
#include "common/common_funcs.h" #include "common/common_funcs.h"
@ -16,6 +17,9 @@
namespace Kernel { namespace Kernel {
// Lists all processes that exist in the current session.
static std::vector<SharedPtr<Process>> process_list;
SharedPtr<CodeSet> CodeSet::Create(std::string name, u64 program_id) { SharedPtr<CodeSet> CodeSet::Create(std::string name, u64 program_id) {
SharedPtr<CodeSet> codeset(new CodeSet); SharedPtr<CodeSet> codeset(new CodeSet);
@ -36,7 +40,9 @@ SharedPtr<Process> Process::Create(std::string&& name) {
process->name = std::move(name); process->name = std::move(name);
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);
return process; return process;
} }
@ -129,6 +135,7 @@ void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) {
} }
vm_manager.LogLayout(Log::Level::Debug); vm_manager.LogLayout(Log::Level::Debug);
status = ProcessStatus::Running;
Kernel::SetupMainThread(entry_point, main_thread_priority, this); Kernel::SetupMainThread(entry_point, main_thread_priority, this);
} }
@ -137,11 +144,11 @@ void Process::LoadModule(SharedPtr<CodeSet> module_, VAddr base_addr) {
memory_region = GetMemoryRegion(flags.memory_region); memory_region = GetMemoryRegion(flags.memory_region);
auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions, auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions,
MemoryState memory_state) { MemoryState memory_state) {
auto vma = vm_manager auto vma = vm_manager
.MapMemoryBlock(segment.addr + base_addr, module_->memory, segment.offset, segment.size, .MapMemoryBlock(segment.addr + base_addr, module_->memory, segment.offset,
memory_state) segment.size, memory_state)
.Unwrap(); .Unwrap();
vm_manager.Reprotect(vma, permissions); vm_manager.Reprotect(vma, permissions);
misc_memory_used += segment.size; misc_memory_used += segment.size;
memory_region->used += segment.size; memory_region->used += segment.size;
@ -299,5 +306,20 @@ ResultCode Process::UnmapMemory(VAddr dst_addr, VAddr /*src_addr*/, u64 size) {
Kernel::Process::Process() {} Kernel::Process::Process() {}
Kernel::Process::~Process() {} Kernel::Process::~Process() {}
SharedPtr<Process> g_current_process; void ClearProcessList() {
process_list.clear();
} }
SharedPtr<Process> GetProcessById(u32 process_id) {
auto itr = std::find_if(
process_list.begin(), process_list.end(),
[&](const SharedPtr<Process>& process) { return process->process_id == process_id; });
if (itr == process_list.end())
return nullptr;
return *itr;
}
SharedPtr<Process> g_current_process;
} // namespace Kernel

View File

@ -8,6 +8,7 @@
#include <cstddef> #include <cstddef>
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector>
#include <boost/container/static_vector.hpp> #include <boost/container/static_vector.hpp>
#include "common/bit_field.h" #include "common/bit_field.h"
#include "common/common_types.h" #include "common/common_types.h"
@ -48,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;
@ -124,6 +127,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++;
@ -181,11 +186,15 @@ public:
ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size); ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size);
private: private:
Process(); Process();
~Process() override; ~Process() override;
}; };
void ClearProcessList();
/// Retrieves a process from the current list of processes.
SharedPtr<Process> GetProcessById(u32 process_id);
extern SharedPtr<Process> g_current_process; extern SharedPtr<Process> g_current_process;
} } // namespace Kernel

View File

@ -9,6 +9,8 @@
#include "core/hle/kernel/client_port.h" #include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/client_session.h" #include "core/hle/kernel/client_session.h"
#include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/mutex.h"
#include "core/hle/kernel/object_address_table.h"
#include "core/hle/kernel/process.h" #include "core/hle/kernel/process.h"
#include "core/hle/kernel/resource_limit.h" #include "core/hle/kernel/resource_limit.h"
#include "core/hle/kernel/sync_object.h" #include "core/hle/kernel/sync_object.h"
@ -45,7 +47,7 @@ static ResultCode MapMemory(VAddr dst_addr, VAddr src_addr, u64 size) {
/// Unmaps a region that was previously mapped with svcMapMemory /// Unmaps a region that was previously mapped with svcMapMemory
static ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size) { static ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size) {
LOG_TRACE(Kernel_SVC, "called, dst_addr=0x%llx, src_addr=0x%llx, size=0x%llx", dst_addr, LOG_TRACE(Kernel_SVC, "called, dst_addr=0x%llx, src_addr=0x%llx, size=0x%llx", dst_addr,
src_addr, size); src_addr, size);
return Kernel::g_current_process->UnmapMemory(dst_addr, src_addr, size); return Kernel::g_current_process->UnmapMemory(dst_addr, src_addr, size);
} }
@ -99,7 +101,8 @@ static ResultCode SendSyncRequest(Kernel::Handle handle) {
static ResultCode GetThreadId(u32* thread_id, Kernel::Handle thread_handle) { static ResultCode GetThreadId(u32* thread_id, Kernel::Handle thread_handle) {
LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle); LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle);
const SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(thread_handle); const SharedPtr<Kernel::Thread> thread =
Kernel::g_handle_table.Get<Kernel::Thread>(thread_handle);
if (!thread) { if (!thread) {
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
} }
@ -177,7 +180,7 @@ static void Break(u64 unk_0, u64 unk_1, u64 unk_2) {
} }
/// Used to output a message on a debug hardware unit - does nothing on a retail unit /// Used to output a message on a debug hardware unit - does nothing on a retail unit
static void OutputDebugString(VAddr address, int len) { static void OutputDebugString(VAddr address, s32 len) {
std::vector<char> string(len); std::vector<char> string(len);
Memory::ReadBlock(address, string.data(), len); Memory::ReadBlock(address, string.data(), len);
LOG_DEBUG(Debug_Emulated, "%.*s", len, string.data()); LOG_DEBUG(Debug_Emulated, "%.*s", len, string.data());
@ -272,6 +275,38 @@ static ResultCode QueryMemory(MemoryInfo* memory_info, PageInfo* page_info, VAdd
return QueryProcessMemory(memory_info, page_info, Kernel::CurrentProcess, addr); return QueryProcessMemory(memory_info, page_info, Kernel::CurrentProcess, addr);
} }
/// Exits the current process
static void ExitProcess() {
LOG_INFO(Kernel_SVC, "Process %u exiting", Kernel::g_current_process->process_id);
ASSERT_MSG(Kernel::g_current_process->status == Kernel::ProcessStatus::Running,
"Process has already exited");
Kernel::g_current_process->status = Kernel::ProcessStatus::Exited;
// Stop all the process threads that are currently waiting for objects.
auto& thread_list = Kernel::GetThreadList();
for (auto& thread : thread_list) {
if (thread->owner_process != Kernel::g_current_process)
continue;
if (thread == Kernel::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
Kernel::GetCurrentThread()->Stop();
Core::System::GetInstance().PrepareReschedule();
}
/// Creates a new thread /// Creates a new thread
static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, VAddr stack_top, static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, VAddr stack_top,
u32 priority, s32 processor_id) { u32 priority, s32 processor_id) {
@ -400,7 +435,7 @@ static const FunctionDef SVC_Table[] = {
{0x04, HLE::Wrap<MapMemory>, "svcMapMemory"}, {0x04, HLE::Wrap<MapMemory>, "svcMapMemory"},
{0x05, HLE::Wrap<UnmapMemory>, "svcUnmapMemory"}, {0x05, HLE::Wrap<UnmapMemory>, "svcUnmapMemory"},
{0x06, HLE::Wrap<QueryMemory>, "svcQueryMemory"}, {0x06, HLE::Wrap<QueryMemory>, "svcQueryMemory"},
{0x07, nullptr, "svcExitProcess"}, {0x07, HLE::Wrap<ExitProcess>, "svcExitProcess"},
{0x08, HLE::Wrap<CreateThread>, "svcCreateThread"}, {0x08, HLE::Wrap<CreateThread>, "svcCreateThread"},
{0x09, HLE::Wrap<StartThread>, "svcStartThread"}, {0x09, HLE::Wrap<StartThread>, "svcStartThread"},
{0x0A, HLE::Wrap<ExitThread>, "svcExitThread"}, {0x0A, HLE::Wrap<ExitThread>, "svcExitThread"},