mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-07-26 20:15:03 +00:00
Improve linux support
This commit is contained in:
parent
b031ba0719
commit
5834b82efb
@ -224,8 +224,6 @@ set(COMMON src/common/logging/backend.cpp
|
|||||||
src/common/debug.h
|
src/common/debug.h
|
||||||
src/common/disassembler.cpp
|
src/common/disassembler.cpp
|
||||||
src/common/disassembler.h
|
src/common/disassembler.h
|
||||||
src/common/discord.cpp
|
|
||||||
src/common/discord.h
|
|
||||||
src/common/endian.h
|
src/common/endian.h
|
||||||
src/common/enum.h
|
src/common/enum.h
|
||||||
src/common/io_file.cpp
|
src/common/io_file.cpp
|
||||||
@ -509,7 +507,7 @@ endif()
|
|||||||
create_target_directory_groups(shadps4)
|
create_target_directory_groups(shadps4)
|
||||||
|
|
||||||
target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak Tracy::TracyClient)
|
target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak Tracy::TracyClient)
|
||||||
target_link_libraries(shadps4 PRIVATE discord-rpc boost vma sirit vulkan-headers xxhash Zydis SPIRV glslang SDL3-shared)
|
target_link_libraries(shadps4 PRIVATE boost vma sirit vulkan-headers xxhash Zydis SPIRV glslang SDL3-shared)
|
||||||
|
|
||||||
if (NOT ENABLE_QT_GUI)
|
if (NOT ENABLE_QT_GUI)
|
||||||
target_link_libraries(shadps4 PRIVATE SDL3-shared)
|
target_link_libraries(shadps4 PRIVATE SDL3-shared)
|
||||||
|
@ -216,17 +216,20 @@ void IOFile::Close() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void* IOFile::GetFileMapping() {
|
uintptr_t IOFile::GetFileMapping() {
|
||||||
#ifdef _WIN64
|
|
||||||
if (file_mapping) {
|
if (file_mapping) {
|
||||||
return file_mapping;
|
return file_mapping;
|
||||||
}
|
}
|
||||||
|
#ifdef _WIN64
|
||||||
const int fd = fileno(file);
|
const int fd = fileno(file);
|
||||||
HANDLE hfile = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
|
HANDLE hfile = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
|
||||||
file_mapping =
|
file_mapping =
|
||||||
CreateFileMapping2(hfile, NULL, FILE_MAP_READ, PAGE_READONLY, SEC_COMMIT, 0, NULL, NULL, 0);
|
CreateFileMapping2(hfile, NULL, FILE_MAP_READ, PAGE_READONLY, SEC_COMMIT, 0, NULL, NULL, 0);
|
||||||
ASSERT_MSG(file_mapping, "{}", Common::GetLastErrorMsg());
|
ASSERT_MSG(file_mapping, "{}", Common::GetLastErrorMsg());
|
||||||
return file_mapping;
|
return file_mapping;
|
||||||
|
#else
|
||||||
|
file_mapping = fileno(file);
|
||||||
|
return file_mapping;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ public:
|
|||||||
return file != nullptr;
|
return file != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* GetFileMapping();
|
uintptr_t GetFileMapping();
|
||||||
|
|
||||||
void Open(const std::filesystem::path& path, FileAccessMode mode,
|
void Open(const std::filesystem::path& path, FileAccessMode mode,
|
||||||
FileType type = FileType::BinaryFile,
|
FileType type = FileType::BinaryFile,
|
||||||
@ -214,7 +214,7 @@ private:
|
|||||||
FileType file_type{};
|
FileType file_type{};
|
||||||
|
|
||||||
std::FILE* file = nullptr;
|
std::FILE* file = nullptr;
|
||||||
void* file_mapping = nullptr;
|
uintptr_t file_mapping = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Common::FS
|
} // namespace Common::FS
|
||||||
|
@ -255,13 +255,14 @@ struct AddressSpace::Impl {
|
|||||||
m_free_regions.insert({start_addr, start_addr + virtual_size});
|
m_free_regions.insert({start_addr, start_addr + virtual_size});
|
||||||
}
|
}
|
||||||
|
|
||||||
void* Map(VAddr virtual_addr, PAddr phys_addr, size_t size, PosixPageProtection prot) {
|
void* Map(VAddr virtual_addr, PAddr phys_addr, size_t size, PosixPageProtection prot,
|
||||||
|
int fd = -1) {
|
||||||
m_free_regions.subtract({virtual_addr, virtual_addr + size});
|
m_free_regions.subtract({virtual_addr, virtual_addr + size});
|
||||||
const int fd = phys_addr != -1 ? backing_fd : -1;
|
const int handle = phys_addr != -1 ? (fd == -1 ? backing_fd : fd) : -1;
|
||||||
const int host_offset = phys_addr != -1 ? phys_addr : 0;
|
const off_t host_offset = phys_addr != -1 ? phys_addr : 0;
|
||||||
const int flag = phys_addr != -1 ? MAP_SHARED : (MAP_ANONYMOUS | MAP_PRIVATE);
|
const int flag = phys_addr != -1 ? MAP_SHARED : (MAP_ANONYMOUS | MAP_PRIVATE);
|
||||||
void* ret = mmap(reinterpret_cast<void*>(virtual_addr), size, prot, MAP_FIXED | flag, fd,
|
void* ret = mmap(reinterpret_cast<void*>(virtual_addr), size, prot, MAP_FIXED | flag,
|
||||||
host_offset);
|
handle, host_offset);
|
||||||
ASSERT_MSG(ret != MAP_FAILED, "mmap failed: {}", strerror(errno));
|
ASSERT_MSG(ret != MAP_FAILED, "mmap failed: {}", strerror(errno));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -324,7 +325,7 @@ void* AddressSpace::Map(VAddr virtual_addr, size_t size, u64 alignment, PAddr ph
|
|||||||
is_exec ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE);
|
is_exec ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* AddressSpace::MapFile(VAddr virtual_addr, size_t size, size_t offset, void* fd) {
|
void* AddressSpace::MapFile(VAddr virtual_addr, size_t size, size_t offset, uintptr_t fd) {
|
||||||
return impl->Map(virtual_addr, offset, size, fd ? PAGE_READONLY : PAGE_READWRITE, fd);
|
return impl->Map(virtual_addr, offset, size, fd ? PAGE_READONLY : PAGE_READWRITE, fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ DECLARE_ENUM_FLAG_OPERATORS(MemoryPermission)
|
|||||||
|
|
||||||
constexpr VAddr SYSTEM_RESERVED = 0x800000000ULL;
|
constexpr VAddr SYSTEM_RESERVED = 0x800000000ULL;
|
||||||
constexpr VAddr CODE_BASE_OFFSET = 0x100000000ULL;
|
constexpr VAddr CODE_BASE_OFFSET = 0x100000000ULL;
|
||||||
constexpr VAddr SYSTEM_MANAGED_MIN = 0x0000040000ULL;
|
constexpr VAddr SYSTEM_MANAGED_MIN = 0x00000400000ULL;
|
||||||
constexpr VAddr SYSTEM_MANAGED_MAX = 0x07FFFFBFFFULL;
|
constexpr VAddr SYSTEM_MANAGED_MAX = 0x07FFFFBFFFULL;
|
||||||
constexpr VAddr USER_MIN = 0x1000000000ULL;
|
constexpr VAddr USER_MIN = 0x1000000000ULL;
|
||||||
constexpr VAddr USER_MAX = 0xFBFFFFFFFFULL;
|
constexpr VAddr USER_MAX = 0xFBFFFFFFFFULL;
|
||||||
@ -63,7 +63,7 @@ public:
|
|||||||
bool exec = false);
|
bool exec = false);
|
||||||
|
|
||||||
/// Memory maps a specified file descriptor.
|
/// Memory maps a specified file descriptor.
|
||||||
void* MapFile(VAddr virtual_addr, size_t size, size_t offset, void* fd);
|
void* MapFile(VAddr virtual_addr, size_t size, size_t offset, uintptr_t fd);
|
||||||
|
|
||||||
/// Unmaps specified virtual memory area.
|
/// Unmaps specified virtual memory area.
|
||||||
void Unmap(VAddr virtual_addr, size_t size, bool has_backing);
|
void Unmap(VAddr virtual_addr, size_t size, bool has_backing);
|
||||||
|
@ -989,7 +989,7 @@ s32 PS4_SYSV_ABI sceGnmSetEmbeddedVsShader(u32* cmdbuf, u32 size, u32 shader_id,
|
|||||||
// a check for zero in the upper part of shader address. In our case, the address is a
|
// a check for zero in the upper part of shader address. In our case, the address is a
|
||||||
// pointer to a stack memory, so the check will likely fail. To workaround it we will
|
// pointer to a stack memory, so the check will likely fail. To workaround it we will
|
||||||
// repeat set shader functionality here as it is trivial.
|
// repeat set shader functionality here as it is trivial.
|
||||||
cmdbuf = PM4CmdSetData::SetShReg(cmdbuf, 0x48u, vs_regs[0], 0u); // SPI_SHADER_PGM_LO_VS
|
cmdbuf = PM4CmdSetData::SetShReg(cmdbuf, 0x48u, vs_regs[0], vs_regs[1]); // SPI_SHADER_PGM_LO_VS
|
||||||
cmdbuf =
|
cmdbuf =
|
||||||
PM4CmdSetData::SetShReg(cmdbuf, 0x4au, vs_regs[2], vs_regs[3]); // SPI_SHADER_PGM_RSRC1_VS
|
PM4CmdSetData::SetShReg(cmdbuf, 0x4au, vs_regs[2], vs_regs[3]); // SPI_SHADER_PGM_RSRC1_VS
|
||||||
cmdbuf = PM4CmdSetData::SetContextReg(cmdbuf, 0x207u, vs_regs[6]); // PA_CL_VS_OUT_CNTL
|
cmdbuf = PM4CmdSetData::SetContextReg(cmdbuf, 0x207u, vs_regs[6]); // PA_CL_VS_OUT_CNTL
|
||||||
|
@ -31,6 +31,10 @@ int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, u16 mode) {
|
|||||||
bool direct = (flags & ORBIS_KERNEL_O_DIRECT) != 0;
|
bool direct = (flags & ORBIS_KERNEL_O_DIRECT) != 0;
|
||||||
bool directory = (flags & ORBIS_KERNEL_O_DIRECTORY) != 0;
|
bool directory = (flags & ORBIS_KERNEL_O_DIRECTORY) != 0;
|
||||||
|
|
||||||
|
if (std::string_view{path} == "/dev/console" || std::string_view{path} == "/dev/deci_tty6") {
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
if (directory) {
|
if (directory) {
|
||||||
LOG_ERROR(Kernel_Fs, "called on directory");
|
LOG_ERROR(Kernel_Fs, "called on directory");
|
||||||
} else {
|
} else {
|
||||||
|
@ -73,18 +73,17 @@ int PS4_SYSV_ABI sceKernelMmap(void* addr, u64 len, int prot, int flags, int fd,
|
|||||||
fmt::ptr(addr), len, prot, flags, fd, offset);
|
fmt::ptr(addr), len, prot, flags, fd, offset);
|
||||||
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
|
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
|
||||||
auto* memory = Core::Memory::Instance();
|
auto* memory = Core::Memory::Instance();
|
||||||
void* handle = NULL;
|
|
||||||
if (fd == -1) {
|
|
||||||
handle =
|
|
||||||
CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, len + offset, NULL);
|
|
||||||
} else {
|
|
||||||
handle = h->GetFile(fd)->f.GetFileMapping();
|
|
||||||
}
|
|
||||||
const auto mem_prot = static_cast<Core::MemoryProt>(prot);
|
const auto mem_prot = static_cast<Core::MemoryProt>(prot);
|
||||||
const auto mem_flags = static_cast<Core::MemoryMapFlags>(flags);
|
const auto mem_flags = static_cast<Core::MemoryMapFlags>(flags);
|
||||||
|
if (fd == -1) {
|
||||||
|
return memory->MapMemory(res, std::bit_cast<VAddr>(addr), len, mem_prot, mem_flags,
|
||||||
|
Core::VMAType::Flexible);
|
||||||
|
} else {
|
||||||
|
const uintptr_t handle = h->GetFile(fd)->f.GetFileMapping();
|
||||||
return memory->MapFile(res, std::bit_cast<VAddr>(addr), len, mem_prot, mem_flags, handle,
|
return memory->MapFile(res, std::bit_cast<VAddr>(addr), len, mem_prot, mem_flags, handle,
|
||||||
offset);
|
offset);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void* PS4_SYSV_ABI posix_mmap(void* addr, u64 len, int prot, int flags, int fd, u64 offset) {
|
void* PS4_SYSV_ABI posix_mmap(void* addr, u64 len, int prot, int flags, int fd, u64 offset) {
|
||||||
void* ptr;
|
void* ptr;
|
||||||
@ -248,6 +247,15 @@ s32 PS4_SYSV_ABI sceKernelGetModuleInfoForUnwind(VAddr addr, int flags,
|
|||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int PS4_SYSV_ABI sceKernelGetModuleInfoFromAddr(VAddr addr, int flags,
|
||||||
|
Core::OrbisKernelModuleInfoEx* info) {
|
||||||
|
LOG_INFO(Lib_Kernel, "called addr = {:#x}, flags = {:#x}", addr, flags);
|
||||||
|
auto* linker = Common::Singleton<Core::Linker>::Instance();
|
||||||
|
auto* module = linker->FindByAddress(addr);
|
||||||
|
*info = module->GetModuleInfoEx();
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceKernelDebugRaiseException() {
|
int PS4_SYSV_ABI sceKernelDebugRaiseException() {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
return 0;
|
return 0;
|
||||||
@ -267,6 +275,10 @@ int PS4_SYSV_ABI sceKernelGetCpumode() {
|
|||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PS4_SYSV_ABI sched_yield() {
|
||||||
|
return std::this_thread::yield();
|
||||||
|
}
|
||||||
|
|
||||||
void LibKernel_Register(Core::Loader::SymbolsResolver* sym) {
|
void LibKernel_Register(Core::Loader::SymbolsResolver* sym) {
|
||||||
// obj
|
// obj
|
||||||
LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &g_stack_chk_guard);
|
LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &g_stack_chk_guard);
|
||||||
@ -292,6 +304,7 @@ void LibKernel_Register(Core::Loader::SymbolsResolver* sym) {
|
|||||||
LIB_FUNCTION("wzvqT4UqKX8", "libkernel", 1, "libkernel", 1, 1, sceKernelLoadStartModule);
|
LIB_FUNCTION("wzvqT4UqKX8", "libkernel", 1, "libkernel", 1, 1, sceKernelLoadStartModule);
|
||||||
LIB_FUNCTION("LwG8g3niqwA", "libkernel", 1, "libkernel", 1, 1, sceKernelDlsym);
|
LIB_FUNCTION("LwG8g3niqwA", "libkernel", 1, "libkernel", 1, 1, sceKernelDlsym);
|
||||||
LIB_FUNCTION("RpQJJVKTiFM", "libkernel", 1, "libkernel", 1, 1, sceKernelGetModuleInfoForUnwind);
|
LIB_FUNCTION("RpQJJVKTiFM", "libkernel", 1, "libkernel", 1, 1, sceKernelGetModuleInfoForUnwind);
|
||||||
|
LIB_FUNCTION("f7KBOafysXo", "libkernel", 1, "libkernel", 1, 1, sceKernelGetModuleInfoFromAddr);
|
||||||
LIB_FUNCTION("VOx8NGmHXTs", "libkernel", 1, "libkernel", 1, 1, sceKernelGetCpumode);
|
LIB_FUNCTION("VOx8NGmHXTs", "libkernel", 1, "libkernel", 1, 1, sceKernelGetCpumode);
|
||||||
|
|
||||||
// equeue
|
// equeue
|
||||||
@ -326,6 +339,7 @@ void LibKernel_Register(Core::Loader::SymbolsResolver* sym) {
|
|||||||
LIB_FUNCTION("NWtTN10cJzE", "libSceLibcInternalExt", 1, "libSceLibcInternal", 1, 1,
|
LIB_FUNCTION("NWtTN10cJzE", "libSceLibcInternalExt", 1, "libSceLibcInternal", 1, 1,
|
||||||
sceLibcHeapGetTraceInfo);
|
sceLibcHeapGetTraceInfo);
|
||||||
LIB_FUNCTION("FxVZqBAA7ks", "libkernel", 1, "libkernel", 1, 1, ps4__write);
|
LIB_FUNCTION("FxVZqBAA7ks", "libkernel", 1, "libkernel", 1, 1, ps4__write);
|
||||||
|
LIB_FUNCTION("6XG4B33N09g", "libScePosix", 1, "libkernel", 1, 1, sched_yield);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Libraries::Kernel
|
} // namespace Libraries::Kernel
|
||||||
|
@ -90,10 +90,10 @@ s32 PS4_SYSV_ABI sceKernelVirtualQuery(const void* addr, int flags, OrbisVirtual
|
|||||||
int PS4_SYSV_ABI sceKernelMapNamedDirectMemory(void** addr, u64 len, int prot, int flags,
|
int PS4_SYSV_ABI sceKernelMapNamedDirectMemory(void** addr, u64 len, int prot, int flags,
|
||||||
s64 directMemoryStart, u64 alignment,
|
s64 directMemoryStart, u64 alignment,
|
||||||
const char* name) {
|
const char* name) {
|
||||||
LOG_INFO(
|
LOG_INFO(Kernel_Vmm,
|
||||||
Kernel_Vmm,
|
"addr = {}, len = {:#x}, prot = {:#x}, flags = {:#x}, directMemoryStart = {:#x}, "
|
||||||
"len = {:#x}, prot = {:#x}, flags = {:#x}, directMemoryStart = {:#x}, alignment = {:#x}",
|
"alignment = {:#x}",
|
||||||
len, prot, flags, directMemoryStart, alignment);
|
fmt::ptr(*addr), len, prot, flags, directMemoryStart, alignment);
|
||||||
|
|
||||||
if (len == 0 || !Common::Is16KBAligned(len)) {
|
if (len == 0 || !Common::Is16KBAligned(len)) {
|
||||||
LOG_ERROR(Kernel_Vmm, "Map size is either zero or not 16KB aligned!");
|
LOG_ERROR(Kernel_Vmm, "Map size is either zero or not 16KB aligned!");
|
||||||
@ -120,11 +120,7 @@ int PS4_SYSV_ABI sceKernelMapNamedDirectMemory(void** addr, u64 len, int prot, i
|
|||||||
|
|
||||||
int PS4_SYSV_ABI sceKernelMapDirectMemory(void** addr, u64 len, int prot, int flags,
|
int PS4_SYSV_ABI sceKernelMapDirectMemory(void** addr, u64 len, int prot, int flags,
|
||||||
s64 directMemoryStart, u64 alignment) {
|
s64 directMemoryStart, u64 alignment) {
|
||||||
LOG_INFO(Kernel_Vmm,
|
LOG_INFO(Kernel_Vmm, "called, redirected to sceKernelMapNamedDirectMemory");
|
||||||
"redirected to sceKernelMapNamedDirectMemory: "
|
|
||||||
"len = {:#x}, prot = {:#x}, flags = {:#x}, directMemoryStart = {:#x}, alignment = "
|
|
||||||
"{:#x}",
|
|
||||||
len, prot, flags, directMemoryStart, alignment);
|
|
||||||
return sceKernelMapNamedDirectMemory(addr, len, prot, flags, directMemoryStart, alignment, "");
|
return sceKernelMapNamedDirectMemory(addr, len, prot, flags, directMemoryStart, alignment, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
#include <semaphore.h>
|
#include <semaphore.h>
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
|
#include "common/error.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/singleton.h"
|
#include "common/singleton.h"
|
||||||
#include "common/thread.h"
|
#include "common/thread.h"
|
||||||
@ -138,9 +139,8 @@ int PS4_SYSV_ABI scePthreadAttrGetdetachstate(const ScePthreadAttr* attr, int* s
|
|||||||
return SCE_KERNEL_ERROR_EINVAL;
|
return SCE_KERNEL_ERROR_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// int result = pthread_attr_getdetachstate(&(*attr)->p, state);
|
// int result = pthread_attr_getdetachstate(&(*attr)->pth_attr, state);
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
*state = ((*attr)->detached ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE);
|
*state = ((*attr)->detached ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE);
|
||||||
|
|
||||||
switch (*state) {
|
switch (*state) {
|
||||||
@ -174,12 +174,9 @@ int PS4_SYSV_ABI scePthreadAttrSetdetachstate(ScePthreadAttr* attr, int detachst
|
|||||||
UNREACHABLE_MSG("Invalid detachstate: {}", detachstate);
|
UNREACHABLE_MSG("Invalid detachstate: {}", detachstate);
|
||||||
}
|
}
|
||||||
|
|
||||||
// int result = pthread_attr_setdetachstate(&(*attr)->pth_attr, pstate); doesn't seem to work
|
// int result = pthread_attr_setdetachstate(&(*attr)->pth_attr, pstate);
|
||||||
// correctly
|
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
(*attr)->detached = (pstate == PTHREAD_CREATE_DETACHED);
|
(*attr)->detached = (pstate == PTHREAD_CREATE_DETACHED);
|
||||||
|
|
||||||
return result == 0 ? SCE_OK : SCE_KERNEL_ERROR_EINVAL;
|
return result == 0 ? SCE_OK : SCE_KERNEL_ERROR_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,7 +243,6 @@ int PS4_SYSV_ABI scePthreadAttrSetschedparam(ScePthreadAttr* attr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI scePthreadAttrGetschedpolicy(const ScePthreadAttr* attr, int* policy) {
|
int PS4_SYSV_ABI scePthreadAttrGetschedpolicy(const ScePthreadAttr* attr, int* policy) {
|
||||||
|
|
||||||
if (policy == nullptr || attr == nullptr || *attr == nullptr) {
|
if (policy == nullptr || attr == nullptr || *attr == nullptr) {
|
||||||
return SCE_KERNEL_ERROR_EINVAL;
|
return SCE_KERNEL_ERROR_EINVAL;
|
||||||
}
|
}
|
||||||
@ -275,16 +271,26 @@ int PS4_SYSV_ABI scePthreadAttrSetschedpolicy(ScePthreadAttr* attr, int policy)
|
|||||||
return SCE_KERNEL_ERROR_EINVAL;
|
return SCE_KERNEL_ERROR_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ppolicy = SCHED_OTHER; // winpthreads only supports SCHED_OTHER
|
int ppolicy = SCHED_OTHER;
|
||||||
if (policy != SCHED_OTHER) {
|
switch (policy) {
|
||||||
LOG_ERROR(Kernel_Pthread, "policy={} not supported by winpthreads\n", policy);
|
case 0:
|
||||||
|
ppolicy = SCHED_OTHER;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
ppolicy = SCHED_FIFO;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
ppolicy = SCHED_OTHER;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
(*attr)->policy = policy;
|
(*attr)->policy = policy;
|
||||||
|
|
||||||
int result = pthread_attr_setschedpolicy(&(*attr)->pth_attr, ppolicy);
|
int result = pthread_attr_setschedpolicy(&(*attr)->pth_attr, ppolicy);
|
||||||
|
|
||||||
return result == 0 ? SCE_OK : SCE_KERNEL_ERROR_EINVAL;
|
return result == 0 ? SCE_OK : SCE_KERNEL_ERROR_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScePthread PS4_SYSV_ABI scePthreadSelf() {
|
ScePthread PS4_SYSV_ABI scePthreadSelf() {
|
||||||
return g_pthread_self;
|
return g_pthread_self;
|
||||||
}
|
}
|
||||||
@ -298,7 +304,6 @@ int PS4_SYSV_ABI scePthreadAttrSetaffinity(ScePthreadAttr* pattr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
(*pattr)->affinity = mask;
|
(*pattr)->affinity = mask;
|
||||||
|
|
||||||
return SCE_OK;
|
return SCE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -391,16 +396,18 @@ int PS4_SYSV_ABI scePthreadSetaffinity(ScePthread thread, const /*SceKernelCpuma
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* createMutex(void* addr) {
|
ScePthreadMutex* createMutex(ScePthreadMutex* addr) {
|
||||||
if (addr == nullptr || *static_cast<ScePthreadMutex*>(addr) != nullptr) {
|
if (addr == nullptr || *addr != nullptr) {
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
static std::mutex mutex;
|
static std::mutex mutex;
|
||||||
std::scoped_lock lk{mutex};
|
std::scoped_lock lk{mutex};
|
||||||
auto vaddr = reinterpret_cast<u64>(addr);
|
if (*addr != nullptr) {
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
const VAddr vaddr = reinterpret_cast<VAddr>(addr);
|
||||||
std::string name = fmt::format("mutex{:#x}", vaddr);
|
std::string name = fmt::format("mutex{:#x}", vaddr);
|
||||||
scePthreadMutexInit(static_cast<ScePthreadMutex*>(addr), nullptr, name.c_str());
|
scePthreadMutexInit(addr, nullptr, name.c_str());
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -468,7 +475,7 @@ int PS4_SYSV_ABI scePthreadMutexattrInit(ScePthreadMutexattr* attr) {
|
|||||||
|
|
||||||
int result = pthread_mutexattr_init(&(*attr)->pth_mutex_attr);
|
int result = pthread_mutexattr_init(&(*attr)->pth_mutex_attr);
|
||||||
|
|
||||||
result = (result == 0 ? scePthreadMutexattrSettype(attr, 2) : result);
|
result = (result == 0 ? scePthreadMutexattrSettype(attr, 1) : result);
|
||||||
result = (result == 0 ? scePthreadMutexattrSetprotocol(attr, 0) : result);
|
result = (result == 0 ? scePthreadMutexattrSetprotocol(attr, 0) : result);
|
||||||
|
|
||||||
switch (result) {
|
switch (result) {
|
||||||
@ -519,22 +526,20 @@ int PS4_SYSV_ABI scePthreadMutexattrSetprotocol(ScePthreadMutexattr* attr, int p
|
|||||||
UNREACHABLE_MSG("Invalid protocol: {}", protocol);
|
UNREACHABLE_MSG("Invalid protocol: {}", protocol);
|
||||||
}
|
}
|
||||||
|
|
||||||
int result = 0; // pthread_mutexattr_setprotocol(&(*attr)->p, pprotocol); //it appears that
|
int result = pthread_mutexattr_setprotocol(&(*attr)->pth_mutex_attr, pprotocol);
|
||||||
// pprotocol has issues in winpthreads
|
|
||||||
(*attr)->pprotocol = pprotocol;
|
(*attr)->pprotocol = pprotocol;
|
||||||
|
|
||||||
return result == 0 ? SCE_OK : SCE_KERNEL_ERROR_EINVAL;
|
return result == 0 ? SCE_OK : SCE_KERNEL_ERROR_EINVAL;
|
||||||
}
|
}
|
||||||
int PS4_SYSV_ABI scePthreadMutexLock(ScePthreadMutex* mutex) {
|
|
||||||
mutex = static_cast<ScePthreadMutex*>(createMutex(mutex));
|
|
||||||
|
|
||||||
|
int PS4_SYSV_ABI scePthreadMutexLock(ScePthreadMutex* mutex) {
|
||||||
|
mutex = createMutex(mutex);
|
||||||
if (mutex == nullptr) {
|
if (mutex == nullptr) {
|
||||||
return SCE_KERNEL_ERROR_EINVAL;
|
return SCE_KERNEL_ERROR_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int result = pthread_mutex_lock(&(*mutex)->pth_mutex);
|
int result = pthread_mutex_lock(&(*mutex)->pth_mutex);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
LOG_TRACE(Kernel_Pthread, "name={}, result={}", (*mutex)->name, result);
|
LOG_TRACE(Kernel_Pthread, "Locked name={}, result={}", (*mutex)->name, result);
|
||||||
}
|
}
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case 0:
|
case 0:
|
||||||
@ -549,20 +554,20 @@ int PS4_SYSV_ABI scePthreadMutexLock(ScePthreadMutex* mutex) {
|
|||||||
return SCE_KERNEL_ERROR_EINVAL;
|
return SCE_KERNEL_ERROR_EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI scePthreadMutexUnlock(ScePthreadMutex* mutex) {
|
int PS4_SYSV_ABI scePthreadMutexUnlock(ScePthreadMutex* mutex) {
|
||||||
mutex = static_cast<ScePthreadMutex*>(createMutex(mutex));
|
mutex = createMutex(mutex);
|
||||||
if (mutex == nullptr) {
|
if (mutex == nullptr) {
|
||||||
return SCE_KERNEL_ERROR_EINVAL;
|
return SCE_KERNEL_ERROR_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int result = pthread_mutex_unlock(&(*mutex)->pth_mutex);
|
int result = pthread_mutex_unlock(&(*mutex)->pth_mutex);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
LOG_TRACE(Kernel_Pthread, "name={}, result={}", (*mutex)->name, result);
|
LOG_TRACE(Kernel_Pthread, "Unlocking name={}, result={}", (*mutex)->name, result);
|
||||||
}
|
}
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case 0:
|
case 0:
|
||||||
return SCE_OK;
|
return SCE_OK;
|
||||||
|
|
||||||
case EINVAL:
|
case EINVAL:
|
||||||
return SCE_KERNEL_ERROR_EINVAL;
|
return SCE_KERNEL_ERROR_EINVAL;
|
||||||
case EPERM:
|
case EPERM:
|
||||||
@ -573,7 +578,6 @@ int PS4_SYSV_ABI scePthreadMutexUnlock(ScePthreadMutex* mutex) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI scePthreadMutexattrDestroy(ScePthreadMutexattr* attr) {
|
int PS4_SYSV_ABI scePthreadMutexattrDestroy(ScePthreadMutexattr* attr) {
|
||||||
|
|
||||||
int result = pthread_mutexattr_destroy(&(*attr)->pth_mutex_attr);
|
int result = pthread_mutexattr_destroy(&(*attr)->pth_mutex_attr);
|
||||||
|
|
||||||
delete *attr;
|
delete *attr;
|
||||||
@ -589,12 +593,16 @@ int PS4_SYSV_ABI scePthreadMutexattrDestroy(ScePthreadMutexattr* attr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void* createCond(void* addr) {
|
ScePthreadCond* createCond(ScePthreadCond* addr) {
|
||||||
if (addr == nullptr || *static_cast<ScePthreadCond*>(addr) != nullptr) {
|
if (addr == nullptr || *addr != nullptr) {
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
auto vaddr = reinterpret_cast<u64>(addr);
|
static std::mutex mutex;
|
||||||
|
std::scoped_lock lk{mutex};
|
||||||
|
if (*addr != nullptr) {
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
const VAddr vaddr = reinterpret_cast<VAddr>(addr);
|
||||||
std::string name = fmt::format("cond{:#x}", vaddr);
|
std::string name = fmt::format("cond{:#x}", vaddr);
|
||||||
scePthreadCondInit(static_cast<ScePthreadCond*>(addr), nullptr, name.c_str());
|
scePthreadCondInit(static_cast<ScePthreadCond*>(addr), nullptr, name.c_str());
|
||||||
return addr;
|
return addr;
|
||||||
@ -654,8 +662,7 @@ int PS4_SYSV_ABI scePthreadCondattrInit(ScePthreadCondattr* attr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI scePthreadCondBroadcast(ScePthreadCond* cond) {
|
int PS4_SYSV_ABI scePthreadCondBroadcast(ScePthreadCond* cond) {
|
||||||
cond = static_cast<ScePthreadCond*>(createCond(cond));
|
cond = createCond(cond);
|
||||||
|
|
||||||
if (cond == nullptr) {
|
if (cond == nullptr) {
|
||||||
return SCE_KERNEL_ERROR_EINVAL;
|
return SCE_KERNEL_ERROR_EINVAL;
|
||||||
}
|
}
|
||||||
@ -668,7 +675,7 @@ int PS4_SYSV_ABI scePthreadCondBroadcast(ScePthreadCond* cond) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI scePthreadCondTimedwait(ScePthreadCond* cond, ScePthreadMutex* mutex, u64 usec) {
|
int PS4_SYSV_ABI scePthreadCondTimedwait(ScePthreadCond* cond, ScePthreadMutex* mutex, u64 usec) {
|
||||||
cond = static_cast<ScePthreadCond*>(createCond(cond));
|
cond = createCond(cond);
|
||||||
if (cond == nullptr) {
|
if (cond == nullptr) {
|
||||||
return SCE_KERNEL_ERROR_EINVAL;
|
return SCE_KERNEL_ERROR_EINVAL;
|
||||||
}
|
}
|
||||||
@ -1032,9 +1039,9 @@ int PS4_SYSV_ABI scePthreadCondSignal(ScePthreadCond* cond) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI scePthreadCondWait(ScePthreadCond* cond, ScePthreadMutex* mutex) {
|
int PS4_SYSV_ABI scePthreadCondWait(ScePthreadCond* cond, ScePthreadMutex* mutex) {
|
||||||
if (cond == nullptr || *cond == nullptr) {
|
cond = createCond(cond);
|
||||||
// return SCE_KERNEL_ERROR_EINVAL;
|
if (cond == nullptr) {
|
||||||
cond = static_cast<ScePthreadCond*>(createCond(cond)); // check this. Kero Blaster.
|
return SCE_KERNEL_ERROR_EINVAL;
|
||||||
}
|
}
|
||||||
if (mutex == nullptr || *mutex == nullptr) {
|
if (mutex == nullptr || *mutex == nullptr) {
|
||||||
return SCE_KERNEL_ERROR_EINVAL;
|
return SCE_KERNEL_ERROR_EINVAL;
|
||||||
@ -1074,7 +1081,7 @@ int PS4_SYSV_ABI scePthreadCondattrDestroy(ScePthreadCondattr* attr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI scePthreadMutexTrylock(ScePthreadMutex* mutex) {
|
int PS4_SYSV_ABI scePthreadMutexTrylock(ScePthreadMutex* mutex) {
|
||||||
mutex = reinterpret_cast<ScePthreadMutex*>(createMutex(mutex));
|
mutex = createMutex(mutex);
|
||||||
if (mutex == nullptr) {
|
if (mutex == nullptr) {
|
||||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||||
}
|
}
|
||||||
@ -1250,7 +1257,7 @@ void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
|
|||||||
LIB_FUNCTION("4qGrR6eoP9Y", "libkernel", 1, "libkernel", 1, 1, scePthreadDetach);
|
LIB_FUNCTION("4qGrR6eoP9Y", "libkernel", 1, "libkernel", 1, 1, scePthreadDetach);
|
||||||
LIB_FUNCTION("3PtV6p3QNX4", "libkernel", 1, "libkernel", 1, 1, scePthreadEqual);
|
LIB_FUNCTION("3PtV6p3QNX4", "libkernel", 1, "libkernel", 1, 1, scePthreadEqual);
|
||||||
LIB_FUNCTION("7Xl257M4VNI", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_equal);
|
LIB_FUNCTION("7Xl257M4VNI", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_equal);
|
||||||
LIB_FUNCTION("7Xl257M4VNI", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_join);
|
LIB_FUNCTION("h9CcP3J0oVM", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_join);
|
||||||
|
|
||||||
LIB_FUNCTION("aI+OeCz8xrQ", "libkernel", 1, "libkernel", 1, 1, scePthreadSelf);
|
LIB_FUNCTION("aI+OeCz8xrQ", "libkernel", 1, "libkernel", 1, 1, scePthreadSelf);
|
||||||
LIB_FUNCTION("EotR8a3ASf4", "libkernel", 1, "libkernel", 1, 1, posix_pthread_self);
|
LIB_FUNCTION("EotR8a3ASf4", "libkernel", 1, "libkernel", 1, 1, posix_pthread_self);
|
||||||
@ -1331,6 +1338,4 @@ void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
|
|||||||
SemaphoreSymbolsRegister(sym);
|
SemaphoreSymbolsRegister(sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Libraries::Kernel
|
} // namespace Libraries::Kernel
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
namespace Core::Loader {
|
namespace Core::Loader {
|
||||||
class SymbolsResolver;
|
class SymbolsResolver;
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "core/libraries/error_codes.h"
|
#include "core/libraries/error_codes.h"
|
||||||
|
#include "core/libraries/kernel/threads/threads.h"
|
||||||
#include "core/libraries/libs.h"
|
#include "core/libraries/libs.h"
|
||||||
#include "threads.h"
|
|
||||||
|
|
||||||
namespace Libraries::Kernel {
|
namespace Libraries::Kernel {
|
||||||
|
|
||||||
@ -25,6 +26,7 @@ bool PthreadKeys::CreateKey(int* key, PthreadKeyDestructor destructor) {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PthreadKeys::GetKey(int key, int thread_id, void** data) {
|
bool PthreadKeys::GetKey(int key, int thread_id, void** data) {
|
||||||
std::scoped_lock lk{m_mutex};
|
std::scoped_lock lk{m_mutex};
|
||||||
|
|
||||||
@ -88,7 +90,6 @@ void* PS4_SYSV_ABI scePthreadGetspecific(OrbisPthreadKey key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI scePthreadSetspecific(OrbisPthreadKey key, /* const*/ void* value) {
|
int PS4_SYSV_ABI scePthreadSetspecific(OrbisPthreadKey key, /* const*/ void* value) {
|
||||||
|
|
||||||
auto id = std::this_thread::get_id();
|
auto id = std::this_thread::get_id();
|
||||||
int thread_id = *(unsigned*)&id;
|
int thread_id = *(unsigned*)&id;
|
||||||
|
|
||||||
|
@ -34,10 +34,23 @@ int PS4_SYSV_ABI posix_pthread_rwlock_init(OrbisPthreadRwlock* rwlock,
|
|||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI posix_pthread_rwlock_rdlock(OrbisPthreadRwlock* rwlock) {
|
OrbisPthreadRwlock* createRwlock(OrbisPthreadRwlock* rwlock) {
|
||||||
if (*rwlock == nullptr) {
|
if (rwlock == nullptr || *rwlock != nullptr) {
|
||||||
posix_pthread_rwlock_init(rwlock, nullptr, nullptr);
|
return rwlock;
|
||||||
}
|
}
|
||||||
|
static std::mutex mutex;
|
||||||
|
std::scoped_lock lk{mutex};
|
||||||
|
if (*rwlock != nullptr) {
|
||||||
|
return rwlock;
|
||||||
|
}
|
||||||
|
const VAddr addr = std::bit_cast<VAddr>(rwlock);
|
||||||
|
const auto name = fmt::format("rwlock{:#x}", addr);
|
||||||
|
posix_pthread_rwlock_init(rwlock, nullptr, name.c_str());
|
||||||
|
return rwlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PS4_SYSV_ABI posix_pthread_rwlock_rdlock(OrbisPthreadRwlock* rwlock) {
|
||||||
|
rwlock = createRwlock(rwlock);
|
||||||
int result = pthread_rwlock_rdlock(&(*rwlock)->pth_rwlock);
|
int result = pthread_rwlock_rdlock(&(*rwlock)->pth_rwlock);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
LOG_ERROR(Kernel_Pthread, "posix_pthread_rwlock_rdlock: error = {}", result);
|
LOG_ERROR(Kernel_Pthread, "posix_pthread_rwlock_rdlock: error = {}", result);
|
||||||
@ -72,6 +85,10 @@ int PS4_SYSV_ABI posix_pthread_rwlock_timedwrlock() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI posix_pthread_rwlock_tryrdlock(OrbisPthreadRwlock* rwlock) {
|
int PS4_SYSV_ABI posix_pthread_rwlock_tryrdlock(OrbisPthreadRwlock* rwlock) {
|
||||||
|
rwlock = createRwlock(rwlock);
|
||||||
|
if (rwlock == nullptr) {
|
||||||
|
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||||
|
}
|
||||||
int result = pthread_rwlock_tryrdlock(&(*rwlock)->pth_rwlock);
|
int result = pthread_rwlock_tryrdlock(&(*rwlock)->pth_rwlock);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
LOG_ERROR(Kernel_Pthread, "posix_pthread_rwlock_tryrdlock: error = {}", result);
|
LOG_ERROR(Kernel_Pthread, "posix_pthread_rwlock_tryrdlock: error = {}", result);
|
||||||
@ -80,6 +97,10 @@ int PS4_SYSV_ABI posix_pthread_rwlock_tryrdlock(OrbisPthreadRwlock* rwlock) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI posix_pthread_rwlock_trywrlock(OrbisPthreadRwlock* rwlock) {
|
int PS4_SYSV_ABI posix_pthread_rwlock_trywrlock(OrbisPthreadRwlock* rwlock) {
|
||||||
|
rwlock = createRwlock(rwlock);
|
||||||
|
if (rwlock == nullptr) {
|
||||||
|
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||||
|
}
|
||||||
int result = pthread_rwlock_trywrlock(&(*rwlock)->pth_rwlock);
|
int result = pthread_rwlock_trywrlock(&(*rwlock)->pth_rwlock);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
LOG_ERROR(Kernel_Pthread, "posix_pthread_rwlock_trywrlock: error = {}", result);
|
LOG_ERROR(Kernel_Pthread, "posix_pthread_rwlock_trywrlock: error = {}", result);
|
||||||
@ -88,6 +109,10 @@ int PS4_SYSV_ABI posix_pthread_rwlock_trywrlock(OrbisPthreadRwlock* rwlock) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI posix_pthread_rwlock_unlock(OrbisPthreadRwlock* rwlock) {
|
int PS4_SYSV_ABI posix_pthread_rwlock_unlock(OrbisPthreadRwlock* rwlock) {
|
||||||
|
rwlock = createRwlock(rwlock);
|
||||||
|
if (rwlock == nullptr) {
|
||||||
|
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||||
|
}
|
||||||
int result = pthread_rwlock_unlock(&(*rwlock)->pth_rwlock);
|
int result = pthread_rwlock_unlock(&(*rwlock)->pth_rwlock);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
LOG_ERROR(Kernel_Pthread, "posix_pthread_rwlock_unlock: error = {}", result);
|
LOG_ERROR(Kernel_Pthread, "posix_pthread_rwlock_unlock: error = {}", result);
|
||||||
@ -96,6 +121,10 @@ int PS4_SYSV_ABI posix_pthread_rwlock_unlock(OrbisPthreadRwlock* rwlock) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI posix_pthread_rwlock_wrlock(OrbisPthreadRwlock* rwlock) {
|
int PS4_SYSV_ABI posix_pthread_rwlock_wrlock(OrbisPthreadRwlock* rwlock) {
|
||||||
|
rwlock = createRwlock(rwlock);
|
||||||
|
if (rwlock == nullptr) {
|
||||||
|
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||||
|
}
|
||||||
int result = pthread_rwlock_wrlock(&(*rwlock)->pth_rwlock);
|
int result = pthread_rwlock_wrlock(&(*rwlock)->pth_rwlock);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
LOG_ERROR(Kernel_Pthread, "posix_pthread_rwlock_wrlock: error = {}", result);
|
LOG_ERROR(Kernel_Pthread, "posix_pthread_rwlock_wrlock: error = {}", result);
|
||||||
@ -274,9 +303,7 @@ int PS4_SYSV_ABI scePthreadRwlockUnlock(OrbisPthreadRwlock* rwlock) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI scePthreadRwlockWrlock(OrbisPthreadRwlock* rwlock) {
|
int PS4_SYSV_ABI scePthreadRwlockWrlock(OrbisPthreadRwlock* rwlock) {
|
||||||
if (rwlock == nullptr || *rwlock == nullptr) {
|
rwlock = createRwlock(rwlock);
|
||||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
|
||||||
}
|
|
||||||
int result = pthread_rwlock_wrlock(&(*rwlock)->pth_rwlock);
|
int result = pthread_rwlock_wrlock(&(*rwlock)->pth_rwlock);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
LOG_ERROR(Kernel_Pthread, "scePthreadRwlockWrlock: error = {}", result);
|
LOG_ERROR(Kernel_Pthread, "scePthreadRwlockWrlock: error = {}", result);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
|
#include <mutex>
|
||||||
#include <boost/intrusive/list.hpp>
|
#include <boost/intrusive/list.hpp>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
@ -17,8 +18,8 @@ using ListBaseHook =
|
|||||||
|
|
||||||
class Semaphore {
|
class Semaphore {
|
||||||
public:
|
public:
|
||||||
Semaphore(s32 init_count, s32 max_count, bool is_fifo)
|
Semaphore(s32 init_count, s32 max_count, const char* name, bool is_fifo)
|
||||||
: token_count{init_count}, max_count{max_count}, is_fifo{is_fifo} {}
|
: name{name}, token_count{init_count}, max_count{max_count}, is_fifo{is_fifo} {}
|
||||||
|
|
||||||
bool Wait(bool can_block, s32 need_count, u64* timeout) {
|
bool Wait(bool can_block, s32 need_count, u64* timeout) {
|
||||||
if (HasAvailableTokens(need_count)) {
|
if (HasAvailableTokens(need_count)) {
|
||||||
@ -131,6 +132,7 @@ private:
|
|||||||
boost::intrusive::list<WaitingThread, boost::intrusive::base_hook<ListBaseHook>,
|
boost::intrusive::list<WaitingThread, boost::intrusive::base_hook<ListBaseHook>,
|
||||||
boost::intrusive::constant_time_size<false>>;
|
boost::intrusive::constant_time_size<false>>;
|
||||||
WaitingThreads wait_list;
|
WaitingThreads wait_list;
|
||||||
|
std::string name;
|
||||||
std::atomic<s32> token_count;
|
std::atomic<s32> token_count;
|
||||||
std::mutex mutex;
|
std::mutex mutex;
|
||||||
s32 max_count;
|
s32 max_count;
|
||||||
@ -145,7 +147,7 @@ s32 PS4_SYSV_ABI sceKernelCreateSema(OrbisKernelSema* sem, const char* pName, u3
|
|||||||
LOG_ERROR(Lib_Kernel, "Semaphore creation parameters are invalid!");
|
LOG_ERROR(Lib_Kernel, "Semaphore creation parameters are invalid!");
|
||||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||||
}
|
}
|
||||||
*sem = new Semaphore(initCount, maxCount, attr == 1);
|
*sem = new Semaphore(initCount, maxCount, pName, attr == 1);
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,9 +63,13 @@ int PS4_SYSV_ABI sceKernelUsleep(u32 microseconds) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI posix_usleep(u32 microseconds) {
|
int PS4_SYSV_ABI posix_usleep(u32 microseconds) {
|
||||||
ASSERT(microseconds >= 1000);
|
#ifdef _WIN64
|
||||||
|
ASSERT(microseconds >= 1000 || microseconds == 0);
|
||||||
std::this_thread::sleep_for(std::chrono::microseconds(microseconds));
|
std::this_thread::sleep_for(std::chrono::microseconds(microseconds));
|
||||||
return 0;
|
return 0;
|
||||||
|
#else
|
||||||
|
return usleep(microseconds);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 PS4_SYSV_ABI sceKernelSleep(u32 seconds) {
|
u32 PS4_SYSV_ABI sceKernelSleep(u32 seconds) {
|
||||||
@ -152,6 +156,7 @@ int PS4_SYSV_ABI gettimeofday(OrbisKernelTimeval* tp, OrbisKernelTimezone* tz) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceKernelGettimezone(OrbisKernelTimezone* tz) {
|
s32 PS4_SYSV_ABI sceKernelGettimezone(OrbisKernelTimezone* tz) {
|
||||||
|
#ifdef _WIN64
|
||||||
ASSERT(tz);
|
ASSERT(tz);
|
||||||
static int tzflag = 0;
|
static int tzflag = 0;
|
||||||
if (!tzflag) {
|
if (!tzflag) {
|
||||||
@ -160,6 +165,13 @@ s32 PS4_SYSV_ABI sceKernelGettimezone(OrbisKernelTimezone* tz) {
|
|||||||
}
|
}
|
||||||
tz->tz_minuteswest = _timezone / 60;
|
tz->tz_minuteswest = _timezone / 60;
|
||||||
tz->tz_dsttime = _daylight;
|
tz->tz_dsttime = _daylight;
|
||||||
|
#else
|
||||||
|
struct timezone tzz;
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, &tzz);
|
||||||
|
tz->tz_dsttime = tzz.tz_dsttime;
|
||||||
|
tz->tz_minuteswest = tzz.tz_minuteswest;
|
||||||
|
#endif
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,6 +188,7 @@ void timeSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
|
|||||||
LIB_FUNCTION("n88vx3C5nW8", "libkernel", 1, "libkernel", 1, 1, gettimeofday);
|
LIB_FUNCTION("n88vx3C5nW8", "libkernel", 1, "libkernel", 1, 1, gettimeofday);
|
||||||
LIB_FUNCTION("n88vx3C5nW8", "libScePosix", 1, "libkernel", 1, 1, gettimeofday);
|
LIB_FUNCTION("n88vx3C5nW8", "libScePosix", 1, "libkernel", 1, 1, gettimeofday);
|
||||||
LIB_FUNCTION("1jfXLRVzisc", "libkernel", 1, "libkernel", 1, 1, sceKernelUsleep);
|
LIB_FUNCTION("1jfXLRVzisc", "libkernel", 1, "libkernel", 1, 1, sceKernelUsleep);
|
||||||
|
LIB_FUNCTION("QcteRwbsnV0", "libkernel", 1, "libkernel", 1, 1, posix_usleep);
|
||||||
LIB_FUNCTION("QcteRwbsnV0", "libScePosix", 1, "libkernel", 1, 1, posix_usleep);
|
LIB_FUNCTION("QcteRwbsnV0", "libScePosix", 1, "libkernel", 1, 1, posix_usleep);
|
||||||
LIB_FUNCTION("-ZR+hG7aDHw", "libkernel", 1, "libkernel", 1, 1, sceKernelSleep);
|
LIB_FUNCTION("-ZR+hG7aDHw", "libkernel", 1, "libkernel", 1, 1, sceKernelSleep);
|
||||||
LIB_FUNCTION("0wu33hunNdE", "libScePosix", 1, "libkernel", 1, 1, sceKernelSleep);
|
LIB_FUNCTION("0wu33hunNdE", "libScePosix", 1, "libkernel", 1, 1, sceKernelSleep);
|
||||||
|
@ -24,15 +24,13 @@ template <StringLiteral name, class R, class... Args, PS4_SYSV_ABI R (*f)(Args..
|
|||||||
struct wrapper_impl<name, PS4_SYSV_ABI R (*)(Args...), f> {
|
struct wrapper_impl<name, PS4_SYSV_ABI R (*)(Args...), f> {
|
||||||
static R PS4_SYSV_ABI wrap(Args... args) {
|
static R PS4_SYSV_ABI wrap(Args... args) {
|
||||||
if (std::string_view(name.value) != "scePthreadEqual" &&
|
if (std::string_view(name.value) != "scePthreadEqual" &&
|
||||||
std::string_view(name.value) != "sceUserServiceGetEvent" &&
|
std::string_view(name.value) != "sceUserServiceGetEvent") {
|
||||||
!std::string_view(name.value).contains("mutex") &&
|
LOG_WARNING(Core_Linker, "Function {} called", name.value);
|
||||||
!std::string_view(name.value).contains("Mutex")) {
|
|
||||||
// LOG_WARNING(Core_Linker, "Function {} called", name.value);
|
|
||||||
}
|
}
|
||||||
if constexpr (std::is_same_v<R, s32> || std::is_same_v<R, u32>) {
|
if constexpr (std::is_same_v<R, s32> || std::is_same_v<R, u32>) {
|
||||||
const int ret = f(args...);
|
const u32 ret = f(args...);
|
||||||
if (ret != 0 && std::string_view(name.value) != "scePthreadEqual") {
|
if (ret != 0 && std::string_view(name.value) != "scePthreadEqual") {
|
||||||
LOG_WARNING(Core_Linker, "Function {} returned {}", name.value, ret);
|
LOG_WARNING(Core_Linker, "Function {} returned {:#x}", name.value, ret);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "core/module.h"
|
#include "core/module.h"
|
||||||
|
@ -91,6 +91,7 @@ int MemoryManager::MapMemory(void** out_addr, VAddr virtual_addr, size_t size, M
|
|||||||
// When virtual addr is zero, force it to virtual_base. The guest cannot pass Fixed
|
// When virtual addr is zero, force it to virtual_base. The guest cannot pass Fixed
|
||||||
// flag so we will take the branch that searches for free (or reserved) mappings.
|
// flag so we will take the branch that searches for free (or reserved) mappings.
|
||||||
virtual_addr = (virtual_addr == 0) ? impl.VirtualBase() : virtual_addr;
|
virtual_addr = (virtual_addr == 0) ? impl.VirtualBase() : virtual_addr;
|
||||||
|
alignment = alignment > 0 ? alignment : 16_KB;
|
||||||
|
|
||||||
VAddr mapped_addr = alignment > 0 ? Common::AlignUp(virtual_addr, alignment) : virtual_addr;
|
VAddr mapped_addr = alignment > 0 ? Common::AlignUp(virtual_addr, alignment) : virtual_addr;
|
||||||
SCOPE_EXIT {
|
SCOPE_EXIT {
|
||||||
@ -141,7 +142,7 @@ int MemoryManager::MapMemory(void** out_addr, VAddr virtual_addr, size_t size, M
|
|||||||
}
|
}
|
||||||
|
|
||||||
int MemoryManager::MapFile(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot,
|
int MemoryManager::MapFile(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot,
|
||||||
MemoryMapFlags flags, void* fd, size_t offset) {
|
MemoryMapFlags flags, uintptr_t fd, size_t offset) {
|
||||||
ASSERT(virtual_addr == 0);
|
ASSERT(virtual_addr == 0);
|
||||||
virtual_addr = impl.VirtualBase();
|
virtual_addr = impl.VirtualBase();
|
||||||
const size_t size_aligned = Common::AlignUp(size, 16_KB);
|
const size_t size_aligned = Common::AlignUp(size, 16_KB);
|
||||||
@ -155,7 +156,7 @@ int MemoryManager::MapFile(void** out_addr, VAddr virtual_addr, size_t size, Mem
|
|||||||
|
|
||||||
// Map the file.
|
// Map the file.
|
||||||
const VAddr mapped_addr = it->second.base;
|
const VAddr mapped_addr = it->second.base;
|
||||||
impl.MapFile(mapped_addr, Common::AlignDown(size, 4_KB), offset, fd);
|
impl.MapFile(mapped_addr, size, offset, fd);
|
||||||
|
|
||||||
// Add virtual memory area
|
// Add virtual memory area
|
||||||
auto& new_vma = AddMapping(mapped_addr, size_aligned);
|
auto& new_vma = AddMapping(mapped_addr, size_aligned);
|
||||||
|
@ -86,7 +86,7 @@ struct VirtualMemoryArea {
|
|||||||
MemoryProt prot = MemoryProt::NoAccess;
|
MemoryProt prot = MemoryProt::NoAccess;
|
||||||
bool disallow_merge = false;
|
bool disallow_merge = false;
|
||||||
std::string name = "";
|
std::string name = "";
|
||||||
void* fd = nullptr;
|
uintptr_t fd = 0;
|
||||||
|
|
||||||
bool Contains(VAddr addr, size_t size) const {
|
bool Contains(VAddr addr, size_t size) const {
|
||||||
return addr >= base && (addr + size) < (base + this->size);
|
return addr >= base && (addr + size) < (base + this->size);
|
||||||
@ -134,7 +134,7 @@ public:
|
|||||||
bool is_exec = false, PAddr phys_addr = -1, u64 alignment = 0);
|
bool is_exec = false, PAddr phys_addr = -1, u64 alignment = 0);
|
||||||
|
|
||||||
int MapFile(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot,
|
int MapFile(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot,
|
||||||
MemoryMapFlags flags, void* fd, size_t offset);
|
MemoryMapFlags flags, uintptr_t fd, size_t offset);
|
||||||
|
|
||||||
void UnmapMemory(VAddr virtual_addr, size_t size);
|
void UnmapMemory(VAddr virtual_addr, size_t size);
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ static constexpr size_t SCE_DBG_NUM_FINGERPRINT = 20;
|
|||||||
|
|
||||||
struct OrbisKernelModuleSegmentInfo {
|
struct OrbisKernelModuleSegmentInfo {
|
||||||
VAddr address;
|
VAddr address;
|
||||||
u64 size;
|
u32 size;
|
||||||
s32 prot;
|
s32 prot;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -125,7 +125,8 @@ static void PatchFsAccess(u8* code, const TLSPattern& tls_pattern, Xbyak::CodeGe
|
|||||||
const auto target_reg = Xbyak::Reg64(tls_pattern.target_reg);
|
const auto target_reg = Xbyak::Reg64(tls_pattern.target_reg);
|
||||||
c.putSeg(fs);
|
c.putSeg(fs);
|
||||||
c.mov(target_reg, qword[SelfInTcbheadOffset]); // Load self member pointer of tcbhead_t.
|
c.mov(target_reg, qword[SelfInTcbheadOffset]); // Load self member pointer of tcbhead_t.
|
||||||
c.add(target_reg, SpecificFirstBlockOffset + sizeof(uintptr_t) + slot * PthreadKeyDataSize);
|
c.add(target_reg, SpecificFirstBlockOffset + sizeof(uintptr_t) * 2 + slot * PthreadKeyDataSize);
|
||||||
|
c.mov(target_reg, qword[target_reg]);
|
||||||
c.jmp(code + total_size); // Return to the instruction right after the mov.
|
c.jmp(code + total_size); // Return to the instruction right after the mov.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,11 +94,11 @@ void Emulator::Run(const std::filesystem::path& file) {
|
|||||||
if (std::filesystem::is_directory(sce_module_folder)) {
|
if (std::filesystem::is_directory(sce_module_folder)) {
|
||||||
for (const auto& entry : std::filesystem::directory_iterator(sce_module_folder)) {
|
for (const auto& entry : std::filesystem::directory_iterator(sce_module_folder)) {
|
||||||
if (entry.path().filename() == "libc.prx" ||
|
if (entry.path().filename() == "libc.prx" ||
|
||||||
entry.path().filename() == "libSceFios2.prx" /*||
|
entry.path().filename() == "libSceFios2.prx" ||
|
||||||
entry.path().filename() == "libSceAudioLatencyEstimation.prx" ||
|
entry.path().filename() == "libSceAudioLatencyEstimation.prx" ||
|
||||||
entry.path().filename() == "libSceJobManager.prx" ||
|
entry.path().filename() == "libSceJobManager.prx" ||
|
||||||
entry.path().filename() == "libSceNpToolkit2.prx" ||
|
entry.path().filename() == "libSceNpToolkit2.prx" ||
|
||||||
entry.path().filename() == "libSceS3DConversion.prx"*/) {
|
entry.path().filename() == "libSceS3DConversion.prx") {
|
||||||
found = true;
|
found = true;
|
||||||
LOG_INFO(Loader, "Loading {}", entry.path().string().c_str());
|
LOG_INFO(Loader, "Loading {}", entry.path().string().c_str());
|
||||||
linker->LoadModule(entry.path());
|
linker->LoadModule(entry.path());
|
||||||
@ -115,15 +115,10 @@ void Emulator::Run(const std::filesystem::path& file) {
|
|||||||
std::jthread([this](std::stop_token stop_token) { linker->Execute(); });
|
std::jthread([this](std::stop_token stop_token) { linker->Execute(); });
|
||||||
|
|
||||||
// Begin main window loop until the application exits
|
// Begin main window loop until the application exits
|
||||||
<<<<<<< HEAD
|
|
||||||
static constexpr std::chrono::milliseconds FlipPeriod{16};
|
|
||||||
=======
|
|
||||||
static constexpr std::chrono::microseconds FlipPeriod{10};
|
static constexpr std::chrono::microseconds FlipPeriod{10};
|
||||||
>>>>>>> 31bd502764f1ac975fc55bd2a788a7e08a9f34ec
|
|
||||||
|
|
||||||
while (window.isOpen()) {
|
while (window.isOpen()) {
|
||||||
window.waitEvent();
|
window.waitEvent();
|
||||||
std::this_thread::sleep_for(FlipPeriod);
|
|
||||||
Libraries::VideoOut::Flip(FlipPeriod);
|
Libraries::VideoOut::Flip(FlipPeriod);
|
||||||
Libraries::VideoOut::Vblank();
|
Libraries::VideoOut::Vblank();
|
||||||
FRAME_END;
|
FRAME_END;
|
||||||
@ -135,7 +130,8 @@ void Emulator::Run(const std::filesystem::path& file) {
|
|||||||
void Emulator::LoadSystemModules(const std::filesystem::path& file) {
|
void Emulator::LoadSystemModules(const std::filesystem::path& file) {
|
||||||
const auto& sys_module_path = Common::FS::GetUserPath(Common::FS::PathType::SysModuleDir);
|
const auto& sys_module_path = Common::FS::GetUserPath(Common::FS::PathType::SysModuleDir);
|
||||||
for (const auto& entry : std::filesystem::directory_iterator(sys_module_path)) {
|
for (const auto& entry : std::filesystem::directory_iterator(sys_module_path)) {
|
||||||
if (entry.path().filename() == "libSceNgs2.sprx") {
|
if (entry.path().filename() == "libSceNgs2.sprx" ||
|
||||||
|
entry.path().filename() == "libSceLibcInternal.sprx") {
|
||||||
LOG_INFO(Loader, "Loading {}", entry.path().string().c_str());
|
LOG_INFO(Loader, "Loading {}", entry.path().string().c_str());
|
||||||
linker->LoadModule(entry.path());
|
linker->LoadModule(entry.path());
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <sys/mman.h>
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
#include "common/thread.h"
|
#include "common/thread.h"
|
||||||
@ -22,8 +23,6 @@ Liverpool::Liverpool() {
|
|||||||
|
|
||||||
Liverpool::~Liverpool() {
|
Liverpool::~Liverpool() {
|
||||||
process_thread.request_stop();
|
process_thread.request_stop();
|
||||||
num_submits = -1;
|
|
||||||
num_submits.notify_one();
|
|
||||||
process_thread.join();
|
process_thread.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,8 +30,10 @@ void Liverpool::Process(std::stop_token stoken) {
|
|||||||
Common::SetCurrentThreadName("GPU_CommandProcessor");
|
Common::SetCurrentThreadName("GPU_CommandProcessor");
|
||||||
|
|
||||||
while (!stoken.stop_requested()) {
|
while (!stoken.stop_requested()) {
|
||||||
num_submits.wait(0);
|
{
|
||||||
|
std::unique_lock lk{submit_mutex};
|
||||||
|
submit_cv.wait(lk, stoken, [this] { return num_submits != 0; });
|
||||||
|
}
|
||||||
if (stoken.stop_requested()) {
|
if (stoken.stop_requested()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -67,7 +68,8 @@ void Liverpool::Process(std::stop_token stoken) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (submit_done) {
|
if (submit_done) {
|
||||||
num_submits.notify_all();
|
std::scoped_lock lk{submit_mutex};
|
||||||
|
submit_cv.notify_all();
|
||||||
submit_done = false;
|
submit_done = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -76,9 +78,8 @@ void Liverpool::Process(std::stop_token stoken) {
|
|||||||
void Liverpool::WaitGpuIdle() {
|
void Liverpool::WaitGpuIdle() {
|
||||||
RENDERER_TRACE;
|
RENDERER_TRACE;
|
||||||
|
|
||||||
while (const auto old = num_submits.load()) {
|
std::unique_lock lk{submit_mutex};
|
||||||
num_submits.wait(old);
|
submit_cv.wait(lk, [this] { return num_submits == 0; });
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Liverpool::Task Liverpool::ProcessCeUpdate(std::span<const u32> ccb) {
|
Liverpool::Task Liverpool::ProcessCeUpdate(std::span<const u32> ccb) {
|
||||||
@ -369,7 +370,6 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
|
|||||||
UNREACHABLE_MSG("Unknown PM4 type 3 opcode {:#x} with count {}",
|
UNREACHABLE_MSG("Unknown PM4 type 3 opcode {:#x} with count {}",
|
||||||
static_cast<u32>(opcode), count);
|
static_cast<u32>(opcode), count);
|
||||||
}
|
}
|
||||||
|
|
||||||
dcb = dcb.subspan(header->type3.NumWords() + 1);
|
dcb = dcb.subspan(header->type3.NumWords() + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -415,8 +415,9 @@ void Liverpool::SubmitGfx(std::span<const u32> dcb, std::span<const u32> ccb) {
|
|||||||
queue.submits.emplace(task.handle);
|
queue.submits.emplace(task.handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::scoped_lock lk{submit_mutex};
|
||||||
++num_submits;
|
++num_submits;
|
||||||
num_submits.notify_one();
|
submit_cv.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Liverpool::SubmitAsc(u32 vqid, std::span<const u32> acb) {
|
void Liverpool::SubmitAsc(u32 vqid, std::span<const u32> acb) {
|
||||||
@ -429,8 +430,9 @@ void Liverpool::SubmitAsc(u32 vqid, std::span<const u32> acb) {
|
|||||||
queue.submits.emplace(task.handle);
|
queue.submits.emplace(task.handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::scoped_lock lk{submit_mutex};
|
||||||
++num_submits;
|
++num_submits;
|
||||||
num_submits.notify_one();
|
submit_cv.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace AmdGpu
|
} // namespace AmdGpu
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "video_core/amdgpu/pixel_format.h"
|
#include "video_core/amdgpu/pixel_format.h"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <condition_variable>
|
||||||
#include <coroutine>
|
#include <coroutine>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <span>
|
#include <span>
|
||||||
@ -865,13 +866,15 @@ public:
|
|||||||
void SubmitAsc(u32 vqid, std::span<const u32> acb);
|
void SubmitAsc(u32 vqid, std::span<const u32> acb);
|
||||||
|
|
||||||
void WaitGpuIdle();
|
void WaitGpuIdle();
|
||||||
|
|
||||||
bool IsGpuIdle() const {
|
bool IsGpuIdle() const {
|
||||||
return num_submits == 0;
|
return num_submits == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotifySubmitDone() {
|
void NotifySubmitDone() {
|
||||||
|
std::scoped_lock lk{submit_mutex};
|
||||||
submit_done = true;
|
submit_done = true;
|
||||||
num_submits.notify_all();
|
submit_cv.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BindRasterizer(Vulkan::Rasterizer* rasterizer_) {
|
void BindRasterizer(Vulkan::Rasterizer* rasterizer_) {
|
||||||
@ -939,7 +942,9 @@ private:
|
|||||||
|
|
||||||
Vulkan::Rasterizer* rasterizer{};
|
Vulkan::Rasterizer* rasterizer{};
|
||||||
std::jthread process_thread{};
|
std::jthread process_thread{};
|
||||||
std::atomic<u32> num_submits{};
|
u32 num_submits{};
|
||||||
|
std::mutex submit_mutex;
|
||||||
|
std::condition_variable_any submit_cv;
|
||||||
std::atomic<bool> submit_done{};
|
std::atomic<bool> submit_done{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user