diff options
| author | bunnei <bunneidev@gmail.com> | 2018-01-01 14:38:34 -0500 | 
|---|---|---|
| committer | bunnei <bunneidev@gmail.com> | 2018-01-01 14:38:34 -0500 | 
| commit | aa7c824ea422152e3e8ac4586a9b94d2c755c23d (patch) | |
| tree | 31dbb609273a9bb4b66b3f40ef0de6fabe7daf2e /src/core/hle | |
| parent | 9b8afed5f74b0b2be87943d1b417146f59f6de36 (diff) | |
svc: Implement svcExitProcess.
Diffstat (limited to 'src/core/hle')
| -rw-r--r-- | src/core/hle/kernel/process.cpp | 32 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.h | 13 | ||||
| -rw-r--r-- | src/core/hle/svc.cpp | 43 | 
3 files changed, 77 insertions, 11 deletions
| diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 35cf6dc95..8e74059ea 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -2,6 +2,7 @@  // Licensed under GPLv2 or any later version  // Refer to the license.txt file included. +#include <algorithm>  #include <memory>  #include "common/assert.h"  #include "common/common_funcs.h" @@ -16,6 +17,9 @@  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(new CodeSet); @@ -36,7 +40,9 @@ SharedPtr<Process> Process::Create(std::string&& name) {      process->name = std::move(name);      process->flags.raw = 0;      process->flags.memory_region.Assign(MemoryRegion::APPLICATION); +    process->status = ProcessStatus::Created; +    process_list.push_back(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); +    status = ProcessStatus::Running;      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);      auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions, -        MemoryState memory_state) { +                          MemoryState memory_state) {          auto vma = vm_manager -            .MapMemoryBlock(segment.addr + base_addr, module_->memory, segment.offset, segment.size, -                memory_state) -            .Unwrap(); +                       .MapMemoryBlock(segment.addr + base_addr, module_->memory, segment.offset, +                                       segment.size, memory_state) +                       .Unwrap();          vm_manager.Reprotect(vma, permissions);          misc_memory_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() {} -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 diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index 3ea8c298f..305275387 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h @@ -8,6 +8,7 @@  #include <cstddef>  #include <memory>  #include <string> +#include <vector>  #include <boost/container/static_vector.hpp>  #include "common/bit_field.h"  #include "common/common_types.h" @@ -48,6 +49,8 @@ union ProcessFlags {      BitField<12, 1, u16> loaded_high; ///< Application loaded high (not at 0x00100000).  }; +enum class ProcessStatus { Created, Running, Exited }; +  class ResourceLimit;  struct MemoryRegionInfo; @@ -124,6 +127,8 @@ public:      u16 kernel_version = 0;      /// The default CPU for this process, threads are scheduled on this cpu by default.      u8 ideal_processor = 0; +    /// Current status of the process +    ProcessStatus status;      /// The id of this process      u32 process_id = next_process_id++; @@ -181,11 +186,15 @@ public:      ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size); -  private:      Process();      ~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; -} +} // namespace Kernel diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index cba94eac3..1ba61d807 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -9,6 +9,8 @@  #include "core/hle/kernel/client_port.h"  #include "core/hle/kernel/client_session.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/resource_limit.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  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, -        src_addr, size); +              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) {      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) {          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 -static void OutputDebugString(VAddr address, int len) { +static void OutputDebugString(VAddr address, s32 len) {      std::vector<char> string(len);      Memory::ReadBlock(address, string.data(), len);      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);  } +/// 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  static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, VAddr stack_top,                                 u32 priority, s32 processor_id) { @@ -400,7 +435,7 @@ static const FunctionDef SVC_Table[] = {      {0x04, HLE::Wrap<MapMemory>, "svcMapMemory"},      {0x05, HLE::Wrap<UnmapMemory>, "svcUnmapMemory"},      {0x06, HLE::Wrap<QueryMemory>, "svcQueryMemory"}, -    {0x07, nullptr, "svcExitProcess"}, +    {0x07, HLE::Wrap<ExitProcess>, "svcExitProcess"},      {0x08, HLE::Wrap<CreateThread>, "svcCreateThread"},      {0x09, HLE::Wrap<StartThread>, "svcStartThread"},      {0x0A, HLE::Wrap<ExitThread>, "svcExitThread"}, | 
