diff options
| author | bunnei <bunneidev@gmail.com> | 2018-10-28 04:38:48 -0400 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-10-28 04:38:48 -0400 | 
| commit | 2239d4711288ffb61c9ac25ce19e3b6b1e15107f (patch) | |
| tree | 90cd62acff8b352bfbdb796e8e947416cb8496f5 | |
| parent | b32be35173b93aafcddaa46a9a596a7223c83701 (diff) | |
| parent | 7de8e3634323bbfcd4242581b2e45493a126710a (diff) | |
Merge pull request #1593 from lioncash/svc
svc: Implement svcGetInfo command 0xF0000002
| -rw-r--r-- | src/core/hle/kernel/process.h | 13 | ||||
| -rw-r--r-- | src/core/hle/kernel/scheduler.cpp | 28 | ||||
| -rw-r--r-- | src/core/hle/kernel/scheduler.h | 19 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 61 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.h | 31 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.h | 11 | 
6 files changed, 128 insertions, 35 deletions
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index 148478488..8d2616c79 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h @@ -202,6 +202,16 @@ public:          return is_64bit_process;      } +    /// Gets the total running time of the process instance in ticks. +    u64 GetCPUTimeTicks() const { +        return total_process_running_time_ticks; +    } + +    /// Updates the total running time, adding the given ticks to it. +    void UpdateCPUTimeTicks(u64 ticks) { +        total_process_running_time_ticks += ticks; +    } +      /**       * Loads process-specifics configuration info with metadata provided       * by an executable. @@ -305,6 +315,9 @@ private:      /// specified by metadata provided to the process during loading.      bool is_64bit_process = true; +    /// Total running time for the process in ticks. +    u64 total_process_running_time_ticks = 0; +      /// Per-process handle table for storing created object handles in.      HandleTable handle_table; diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp index 1342c597e..5a5f4cef1 100644 --- a/src/core/hle/kernel/scheduler.cpp +++ b/src/core/hle/kernel/scheduler.cpp @@ -9,6 +9,7 @@  #include "common/logging/log.h"  #include "core/arm/arm_interface.h"  #include "core/core.h" +#include "core/core_timing.h"  #include "core/hle/kernel/kernel.h"  #include "core/hle/kernel/process.h"  #include "core/hle/kernel/scheduler.h" @@ -34,6 +35,10 @@ Thread* Scheduler::GetCurrentThread() const {      return current_thread.get();  } +u64 Scheduler::GetLastContextSwitchTicks() const { +    return last_context_switch_time; +} +  Thread* Scheduler::PopNextReadyThread() {      Thread* next = nullptr;      Thread* thread = GetCurrentThread(); @@ -54,7 +59,10 @@ Thread* Scheduler::PopNextReadyThread() {  }  void Scheduler::SwitchContext(Thread* new_thread) { -    Thread* previous_thread = GetCurrentThread(); +    Thread* const previous_thread = GetCurrentThread(); +    Process* const previous_process = Core::CurrentProcess(); + +    UpdateLastContextSwitchTime(previous_thread, previous_process);      // Save context for previous thread      if (previous_thread) { @@ -78,8 +86,6 @@ void Scheduler::SwitchContext(Thread* new_thread) {          // Cancel any outstanding wakeup events for this thread          new_thread->CancelWakeupTimer(); -        auto* const previous_process = Core::CurrentProcess(); -          current_thread = new_thread;          ready_queue.remove(new_thread->GetPriority(), new_thread); @@ -102,6 +108,22 @@ void Scheduler::SwitchContext(Thread* new_thread) {      }  } +void Scheduler::UpdateLastContextSwitchTime(Thread* thread, Process* process) { +    const u64 prev_switch_ticks = last_context_switch_time; +    const u64 most_recent_switch_ticks = CoreTiming::GetTicks(); +    const u64 update_ticks = most_recent_switch_ticks - prev_switch_ticks; + +    if (thread != nullptr) { +        thread->UpdateCPUTimeTicks(update_ticks); +    } + +    if (process != nullptr) { +        process->UpdateCPUTimeTicks(update_ticks); +    } + +    last_context_switch_time = most_recent_switch_ticks; +} +  void Scheduler::Reschedule() {      std::lock_guard<std::mutex> lock(scheduler_mutex); diff --git a/src/core/hle/kernel/scheduler.h b/src/core/hle/kernel/scheduler.h index 2c94641ec..c63032b7d 100644 --- a/src/core/hle/kernel/scheduler.h +++ b/src/core/hle/kernel/scheduler.h @@ -17,6 +17,8 @@ class ARM_Interface;  namespace Kernel { +class Process; +  class Scheduler final {  public:      explicit Scheduler(Core::ARM_Interface& cpu_core); @@ -31,6 +33,9 @@ public:      /// Gets the current running thread      Thread* GetCurrentThread() const; +    /// Gets the timestamp for the last context switch in ticks. +    u64 GetLastContextSwitchTicks() const; +      /// Adds a new thread to the scheduler      void AddThread(SharedPtr<Thread> thread, u32 priority); @@ -64,6 +69,19 @@ private:       */      void SwitchContext(Thread* new_thread); +    /** +     * Called on every context switch to update the internal timestamp +     * This also updates the running time ticks for the given thread and +     * process using the following difference: +     * +     * ticks += most_recent_ticks - last_context_switch_ticks +     * +     * The internal tick timestamp for the scheduler is simply the +     * most recent tick count retrieved. No special arithmetic is +     * applied to it. +     */ +    void UpdateLastContextSwitchTime(Thread* thread, Process* process); +      /// Lists all thread ids that aren't deleted/etc.      std::vector<SharedPtr<Thread>> thread_list; @@ -73,6 +91,7 @@ private:      SharedPtr<Thread> current_thread = nullptr;      Core::ARM_Interface& cpu_core; +    u64 last_context_switch_time = 0;      static std::mutex scheduler_mutex;  }; diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index a5302d924..4e490e2b5 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -467,6 +467,37 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)      LOG_TRACE(Kernel_SVC, "called info_id=0x{:X}, info_sub_id=0x{:X}, handle=0x{:08X}", info_id,                info_sub_id, handle); +    enum class GetInfoType : u64 { +        // 1.0.0+ +        AllowedCpuIdBitmask = 0, +        AllowedThreadPrioBitmask = 1, +        MapRegionBaseAddr = 2, +        MapRegionSize = 3, +        HeapRegionBaseAddr = 4, +        HeapRegionSize = 5, +        TotalMemoryUsage = 6, +        TotalHeapUsage = 7, +        IsCurrentProcessBeingDebugged = 8, +        ResourceHandleLimit = 9, +        IdleTickCount = 10, +        RandomEntropy = 11, +        PerformanceCounter = 0xF0000002, +        // 2.0.0+ +        ASLRRegionBaseAddr = 12, +        ASLRRegionSize = 13, +        NewMapRegionBaseAddr = 14, +        NewMapRegionSize = 15, +        // 3.0.0+ +        IsVirtualAddressMemoryEnabled = 16, +        PersonalMmHeapUsage = 17, +        TitleId = 18, +        // 4.0.0+ +        PrivilegedProcessId = 19, +        // 5.0.0+ +        UserExceptionContextAddr = 20, +        ThreadTickCount = 0xF0000002, +    }; +      const auto* current_process = Core::CurrentProcess();      const auto& vm_manager = current_process->VMManager(); @@ -529,6 +560,36 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)                      "(STUBBED) Attempted to query user exception context address, returned 0");          *result = 0;          break; +    case GetInfoType::ThreadTickCount: { +        constexpr u64 num_cpus = 4; +        if (info_sub_id != 0xFFFFFFFFFFFFFFFF && info_sub_id >= num_cpus) { +            return ERR_INVALID_COMBINATION_KERNEL; +        } + +        const auto thread = +            current_process->GetHandleTable().Get<Thread>(static_cast<Handle>(handle)); +        if (!thread) { +            return ERR_INVALID_HANDLE; +        } + +        auto& system = Core::System::GetInstance(); +        const auto& scheduler = system.CurrentScheduler(); +        const auto* const current_thread = scheduler.GetCurrentThread(); +        const bool same_thread = current_thread == thread; + +        const u64 prev_ctx_ticks = scheduler.GetLastContextSwitchTicks(); +        u64 out_ticks = 0; +        if (same_thread && info_sub_id == 0xFFFFFFFFFFFFFFFF) { +            const u64 thread_ticks = current_thread->GetTotalCPUTimeTicks(); + +            out_ticks = thread_ticks + (CoreTiming::GetTicks() - prev_ctx_ticks); +        } else if (same_thread && info_sub_id == system.CurrentCoreIndex()) { +            out_ticks = CoreTiming::GetTicks() - prev_ctx_ticks; +        } + +        *result = out_ticks; +        break; +    }      default:          UNIMPLEMENTED();      } diff --git a/src/core/hle/kernel/svc.h b/src/core/hle/kernel/svc.h index 554a5e328..b06aac4ec 100644 --- a/src/core/hle/kernel/svc.h +++ b/src/core/hle/kernel/svc.h @@ -24,37 +24,6 @@ struct PageInfo {      u64 flags;  }; -/// Values accepted by svcGetInfo -enum class GetInfoType : u64 { -    // 1.0.0+ -    AllowedCpuIdBitmask = 0, -    AllowedThreadPrioBitmask = 1, -    MapRegionBaseAddr = 2, -    MapRegionSize = 3, -    HeapRegionBaseAddr = 4, -    HeapRegionSize = 5, -    TotalMemoryUsage = 6, -    TotalHeapUsage = 7, -    IsCurrentProcessBeingDebugged = 8, -    ResourceHandleLimit = 9, -    IdleTickCount = 10, -    RandomEntropy = 11, -    PerformanceCounter = 0xF0000002, -    // 2.0.0+ -    ASLRRegionBaseAddr = 12, -    ASLRRegionSize = 13, -    NewMapRegionBaseAddr = 14, -    NewMapRegionSize = 15, -    // 3.0.0+ -    IsVirtualAddressMemoryEnabled = 16, -    PersonalMmHeapUsage = 17, -    TitleId = 18, -    // 4.0.0+ -    PrivilegedProcessId = 19, -    // 5.0.0+ -    UserExceptionContextAddr = 20, -}; -  void CallSVC(u32 immediate);  } // namespace Kernel diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index f4d7bd235..4a6e11239 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -258,6 +258,14 @@ public:          return last_running_ticks;      } +    u64 GetTotalCPUTimeTicks() const { +        return total_cpu_time_ticks; +    } + +    void UpdateCPUTimeTicks(u64 ticks) { +        total_cpu_time_ticks += ticks; +    } +      s32 GetProcessorID() const {          return processor_id;      } @@ -378,7 +386,8 @@ private:      u32 nominal_priority = 0; ///< Nominal thread priority, as set by the emulated application      u32 current_priority = 0; ///< Current thread priority, can be temporarily changed -    u64 last_running_ticks = 0; ///< CPU tick when thread was last running +    u64 total_cpu_time_ticks = 0; ///< Total CPU running ticks. +    u64 last_running_ticks = 0;   ///< CPU tick when thread was last running      s32 processor_id = 0;  | 
