common: Rework timekeeping with native RDTSC and port to linux

This commit is contained in:
GPUCode 2024-02-15 00:52:57 +02:00
parent acfa56f6bc
commit fe43558779
37 changed files with 818 additions and 279 deletions

View file

@ -1,5 +1,5 @@
#include "gpu_memory.h"
#include <atomic>
#include <xxh3.h>
#include "common/singleton.h"

View file

@ -2,8 +2,9 @@
#include "common/types.h"
#include <vector>
#include <vulkan/vulkan_core.h>
#include <vulkan/vulkan.h>
#include <mutex>
#include <memory>
namespace HLE::Libs::Graphics {

View file

@ -1,4 +1,6 @@
#pragma once
#include <atomic>
#include <mutex>
#include <string>
#include <vector>
@ -52,4 +54,4 @@ class HandleTable {
std::mutex m_mutex;
};
} // namespace Core::FileSys
} // namespace Core::FileSys

View file

@ -1,6 +1,5 @@
#include "common/debug.h"
#include "common/timer.h"
#include "core/hle/kernel/objects/event_queue.h"
#include "core/hle/kernel/Objects/event_queue.h"
namespace Core::Kernel {
@ -24,28 +23,19 @@ int EqueueInternal::addEvent(const EqueueEvent& event) {
int EqueueInternal::waitForEvents(SceKernelEvent* ev, int num, u32 micros) {
std::unique_lock lock{m_mutex};
int ret = 0;
u32 timeElapsed = 0;
Common::Timer t;
t.Start();
const auto predicate = [&] {
ret = getTriggeredEvents(ev, num);
return ret > 0;
};
for (;;) {
int ret = getTriggeredEvents(ev, num);
if (ret > 0 || (timeElapsed >= micros && micros != 0)) {
return ret;
}
if (micros == 0) {
m_cond.wait(lock);
} else {
m_cond.wait_for(lock, std::chrono::microseconds(micros - timeElapsed));
}
timeElapsed = static_cast<uint32_t>(t.GetTimeSec() * 1000000.0);
if (micros == 0) {
m_cond.wait(lock, predicate);
} else {
m_cond.wait_for(lock, std::chrono::microseconds(micros), predicate);
}
return 0;
return ret;
}
bool EqueueInternal::triggerEvent(u64 ident, s16 filter, void* trigger_data) {

View file

@ -3,6 +3,7 @@
#include <mutex>
#include <string>
#include <vector>
#include <condition_variable>
#include "common/types.h"
namespace Core::Kernel {

View file

@ -1,4 +1,4 @@
#include "core/hle/kernel/objects/physical_memory.h"
#include "core/hle/kernel/Objects/physical_memory.h"
namespace Core::Kernel {

View file

@ -1,6 +1,6 @@
#pragma once
#include "core/hle/kernel/objects/event_queue.h"
#include "core/hle/kernel/Objects/event_queue.h"
namespace Core::Kernel {

View file

@ -4,35 +4,35 @@
namespace Core::Libraries::LibC {
float PS4_SYSV_ABI ps4_atan2f(float y, float x) {
return std::atan2f(y, x);
return atan2f(y, x);
}
float PS4_SYSV_ABI ps4_acosf(float num) {
return std::acosf(num);
return acosf(num);
}
float PS4_SYSV_ABI ps4_tanf(float num) {
return std::tanf(num);
return tanf(num);
}
float PS4_SYSV_ABI ps4_asinf(float num) {
return std::asinf(num);
return asinf(num);
}
double PS4_SYSV_ABI ps4_pow(double base, double exponent) {
return std::pow(base, exponent);
return pow(base, exponent);
}
double PS4_SYSV_ABI ps4__Sin(double x) {
return std::sin(x);
return sin(x);
}
float PS4_SYSV_ABI ps4__Fsin(float arg) {
return std::sinf(arg);
return sinf(arg);
}
double PS4_SYSV_ABI ps4_exp2(double arg) {
return std::exp2(arg);
return exp2(arg);
}
} // namespace Core::Libraries::LibC

View file

@ -12,7 +12,7 @@ int PS4_SYSV_ABI ps4_printf(VA_ARGS) {
}
int PS4_SYSV_ABI ps4_fprintf(FILE* file, VA_ARGS) {
int fd = _fileno(file);
int fd = fileno(file);
if (fd == 1 || fd == 2) { // output stdout and stderr to console
VA_CTX(ctx);
return printf_ctx(&ctx);

View file

@ -15,6 +15,8 @@
#ifdef _WIN64
#include <windows.h>
#include <io.h>
#else
#include <sys/mman.h>
#endif
#include "thread_management.h"
@ -56,6 +58,7 @@ int* PS4_SYSV_ABI __Error() { return &libc_error; }
#define PROT_WRITE 0x2
int PS4_SYSV_ABI sceKernelMmap(void* addr, u64 len, int prot, int flags, int fd, off_t offset, void** res) {
#ifdef _WIN64
PRINT_FUNCTION_NAME();
if (prot > 3) // READ,WRITE or bitwise READ | WRITE supported
{
@ -86,6 +89,14 @@ int PS4_SYSV_ABI sceKernelMmap(void* addr, u64 len, int prot, int flags, int fd,
}
*res = ret;
return 0;
#else
void* result = mmap(addr, len, prot, flags, fd, offset);
if (result != MAP_FAILED) {
*res = result;
return 0;
}
std::abort();
#endif
}
PS4_SYSV_ABI void* posix_mmap(void* addr, u64 len, int prot, int flags, int fd, u64 offset) {

View file

@ -1,27 +1,31 @@
#include "common/timer.h"
#include "common/native_clock.h"
#include "core/hle/libraries/libkernel/time_management.h"
#include "core/hle/libraries/libs.h"
#include "emuTimer.h"
namespace Core::Libraries::LibKernel {
static u64 initial_ptc;
static std::unique_ptr<Common::NativeClock> clock;
u64 PS4_SYSV_ABI sceKernelGetProcessTime() {
return static_cast<u64>(Emulator::emuTimer::getTimeMsec() * 1000.0); // return time in microseconds
return clock->GetProcessTimeUS();
}
u64 PS4_SYSV_ABI sceKernelGetProcessTimeCounter() {
return Emulator::emuTimer::getTimeCounter();
return clock->GetUptime() - initial_ptc;
}
u64 PS4_SYSV_ABI sceKernelGetProcessTimeCounterFrequency() {
return Emulator::emuTimer::getTimeFrequency();
return clock->GetTscFrequency();
}
u64 PS4_SYSV_ABI sceKernelReadTsc() {
return Common::Timer::getQueryPerformanceCounter();
return clock->GetUptime();
}
void timeSymbolsRegister(Loader::SymbolsResolver* sym) {
clock = std::make_unique<Common::NativeClock>();
initial_ptc = clock->GetUptime();
LIB_FUNCTION("4J2sUJmuHZQ", "libkernel", 1, "libkernel", 1, 1, sceKernelGetProcessTime);
LIB_FUNCTION("fgxnMeTNUtY", "libkernel", 1, "libkernel", 1, 1, sceKernelGetProcessTimeCounter);
LIB_FUNCTION("BNowx2l588E", "libkernel", 1, "libkernel", 1, 1, sceKernelGetProcessTimeCounterFrequency);

View file

@ -658,12 +658,12 @@ void Linker::Resolve(const std::string& name, int Symtype, Module* m, Loader::Sy
}
else
{
__debugbreak();//den tha prepei na ftasoume edo
//__debugbreak();//den tha prepei na ftasoume edo
}
}
else
{
__debugbreak();//oute edo mallon
//__debugbreak();//oute edo mallon
}
}

View file

@ -5,7 +5,7 @@
namespace Core::Loader {
constexpr bool log_file_loader = true; // disable it to disable logging
constexpr bool log_file_loader = false; // disable it to disable logging
static std::string_view getProgramTypeName(program_type_es type) {
switch (type) {

View file

@ -79,7 +79,8 @@ bool memory_protect(u64 address, u64 size, MemoryMode mode, MemoryMode* old_mode
}
return true;
#else
#error Unimplement memory_protect function
int ret = mprotect(reinterpret_cast<void*>(address), size, convertMemoryMode(mode));
return true;
#endif
}
@ -117,6 +118,7 @@ bool memory_patch(u64 vaddr, u64 value) {
static u64 AlignUp(u64 pos, u64 align) { return (align != 0 ? (pos + (align - 1)) & ~(align - 1) : pos); }
u64 memory_alloc_aligned(u64 address, u64 size, MemoryMode mode, u64 alignment) {
#ifdef _WIN64
// try allocate aligned address inside user area
MEM_ADDRESS_REQUIREMENTS req{};
MEM_EXTENDED_PARAMETER param{};
@ -134,5 +136,13 @@ u64 memory_alloc_aligned(u64 address, u64 size, MemoryMode mode, u64 alignment)
LOG_ERROR_IF(true, "VirtualAlloc2() failed: 0x{:X}\n", err);
}
return ptr;
#else
void* hint_address = reinterpret_cast<void*>(AlignUp(address, alignment));
void* ptr = mmap(hint_address, size, convertMemoryMode(mode), MAP_ANON | MAP_PRIVATE, -1, 0);
if (ptr == MAP_FAILED) {
std::abort();
}
return reinterpret_cast<u64>(ptr);
#endif
}
} // namespace VirtualMemory