summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2018-10-28 09:38:48 +0100
committerGitHub <noreply@github.com>2018-10-28 09:38:48 +0100
commit2239d4711288ffb61c9ac25ce19e3b6b1e15107f (patch)
tree90cd62acff8b352bfbdb796e8e947416cb8496f5
parentMerge pull request #1581 from FreddyFunk/macosx-target-version (diff)
parentsvc: Localize the GetInfo enum class to the function itself (diff)
downloadyuzu-2239d4711288ffb61c9ac25ce19e3b6b1e15107f.tar
yuzu-2239d4711288ffb61c9ac25ce19e3b6b1e15107f.tar.gz
yuzu-2239d4711288ffb61c9ac25ce19e3b6b1e15107f.tar.bz2
yuzu-2239d4711288ffb61c9ac25ce19e3b6b1e15107f.tar.lz
yuzu-2239d4711288ffb61c9ac25ce19e3b6b1e15107f.tar.xz
yuzu-2239d4711288ffb61c9ac25ce19e3b6b1e15107f.tar.zst
yuzu-2239d4711288ffb61c9ac25ce19e3b6b1e15107f.zip
-rw-r--r--src/core/hle/kernel/process.h13
-rw-r--r--src/core/hle/kernel/scheduler.cpp28
-rw-r--r--src/core/hle/kernel/scheduler.h19
-rw-r--r--src/core/hle/kernel/svc.cpp61
-rw-r--r--src/core/hle/kernel/svc.h31
-rw-r--r--src/core/hle/kernel/thread.h11
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;