kernel: Rework keys

This commit is contained in:
IndecisiveTurtle 2024-06-15 13:40:40 +03:00
parent 1307be09db
commit b7b1487d99
6 changed files with 40 additions and 100 deletions

View file

@ -85,7 +85,7 @@ struct AddressSpace::Impl {
}
}
void* Map(VAddr virtual_addr, PAddr phys_addr, size_t size, ULONG prot, HANDLE fd = nullptr) {
void* Map(VAddr virtual_addr, PAddr phys_addr, size_t size, ULONG prot, uintptr_t fd = 0) {
const auto it = placeholders.find(virtual_addr);
ASSERT_MSG(it != placeholders.end(), "Cannot map already mapped region");
ASSERT_MSG(virtual_addr >= it->lower() && virtual_addr + size <= it->upper(),
@ -117,7 +117,7 @@ struct AddressSpace::Impl {
// Perform the map.
void* ptr = nullptr;
if (phys_addr != -1) {
HANDLE backing = fd ? fd : backing_handle;
HANDLE backing = fd ? reinterpret_cast<HANDLE>(fd) : backing_handle;
ptr = MapViewOfFile3(backing, process, reinterpret_cast<PVOID>(virtual_addr), phys_addr,
size, MEM_REPLACE_PLACEHOLDER, prot, nullptr, 0);
} else {

View file

@ -881,6 +881,11 @@ int PS4_SYSV_ABI scePthreadAttrGet(ScePthread thread, ScePthreadAttr* attr) {
static void cleanup_thread(void* arg) {
auto* thread = static_cast<ScePthread>(arg);
for (const auto& [key, destructor] : thread->key_destructors) {
if (void* value = pthread_getspecific(key); value != nullptr) {
destructor(value);
}
}
thread->is_almost_done = true;
}
@ -899,7 +904,7 @@ static void* run_thread(void* arg) {
}
int PS4_SYSV_ABI scePthreadCreate(ScePthread* thread, const ScePthreadAttr* attr,
pthreadEntryFunc start_routine, void* arg, const char* name) {
PthreadEntryFunc start_routine, void* arg, const char* name) {
if (thread == nullptr) {
return SCE_KERNEL_ERROR_EINVAL;
}
@ -1161,7 +1166,7 @@ int PS4_SYSV_ABI posix_pthread_attr_setdetachstate(ScePthreadAttr* attr, int det
}
int PS4_SYSV_ABI posix_pthread_create_name_np(ScePthread* thread, const ScePthreadAttr* attr,
pthreadEntryFunc start_routine, void* arg,
PthreadEntryFunc start_routine, void* arg,
const char* name) {
LOG_INFO(Kernel_Pthread, "posix pthread_create redirect to scePthreadCreate: name = {}", name);
@ -1176,7 +1181,7 @@ int PS4_SYSV_ABI posix_pthread_create_name_np(ScePthread* thread, const ScePthre
}
int PS4_SYSV_ABI posix_pthread_create(ScePthread* thread, const ScePthreadAttr* attr,
pthreadEntryFunc start_routine, void* arg) {
PthreadEntryFunc start_routine, void* arg) {
return posix_pthread_create_name_np(thread, attr, start_routine, arg, "NoName");
}
@ -1240,19 +1245,7 @@ int PS4_SYSV_ABI scePthreadSetschedparam(ScePthread thread, int policy,
int PS4_SYSV_ABI scePthreadOnce(int* once_control, void (*init_routine)(void)) {
return pthread_once(reinterpret_cast<pthread_once_t*>(once_control), init_routine);
}
int PS4_SYSV_ABI posix_pthread_create(ScePthread* thread, const ScePthreadAttr* attr,
pthreadEntryFunc start_routine, void* arg) {
LOG_INFO(Kernel_Pthread, "posix pthread_create redirect to scePthreadCreate");
int result = scePthreadCreate(thread, attr, start_routine, arg, "");
if (result != 0) {
int rt = result > SCE_KERNEL_ERROR_UNKNOWN && result <= SCE_KERNEL_ERROR_ESTOP
? result + -SCE_KERNEL_ERROR_UNKNOWN
: POSIX_EOTHER;
return rt;
}
return result;
}
void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("lZzFeSxPl08", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_setcancelstate);
LIB_FUNCTION("0TyVk4MSLt0", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_cond_init);
@ -1349,6 +1342,7 @@ void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
// libs
RwlockSymbolsRegister(sym);
SemaphoreSymbolsRegister(sym);
KeySymbolsRegister(sym);
}
} // namespace Libraries::Kernel

View file

@ -39,22 +39,24 @@ using ScePthreadCond = PthreadCondInternal*;
using ScePthreadCondattr = PthreadCondAttrInternal*;
using OrbisPthreadRwlock = PthreadRwInternal*;
using OrbisPthreadRwlockattr = PthreadRwLockAttrInternal*;
using OrbisPthreadKey = int;
using PthreadKeyDestructor = PS4_SYSV_ABI void (*)(void*);
using OrbisPthreadKey = u32;
using pthreadEntryFunc = PS4_SYSV_ABI void* (*)(void*);
using PthreadKeyDestructor = PS4_SYSV_ABI void (*)(void*);
using PthreadEntryFunc = PS4_SYSV_ABI void* (*)(void*);
struct PthreadInternal {
u8 reserved[4096];
std::string name;
pthread_t pth;
ScePthreadAttr attr;
pthreadEntryFunc entry;
PthreadEntryFunc entry;
void* arg;
std::atomic_bool is_started;
std::atomic_bool is_detached;
std::atomic_bool is_almost_done;
std::atomic_bool is_free;
using Destructor = std::pair<OrbisPthreadKey, PthreadKeyDestructor>;
std::vector<Destructor> key_destructors;
};
struct PthreadAttrInternal {
@ -195,7 +197,7 @@ int PS4_SYSV_ABI scePthreadAttrSetaffinity(ScePthreadAttr* pattr,
const /*SceKernelCpumask*/ u64 mask);
int PS4_SYSV_ABI scePthreadSetaffinity(ScePthread thread, const /*SceKernelCpumask*/ u64 mask);
int PS4_SYSV_ABI scePthreadCreate(ScePthread* thread, const ScePthreadAttr* attr,
pthreadEntryFunc start_routine, void* arg, const char* name);
PthreadEntryFunc start_routine, void* arg, const char* name);
/***
* Mutex calls

View file

@ -1,103 +1,47 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <thread>
#include "common/logging/log.h"
#include "core/libraries/error_codes.h"
#include "core/libraries/kernel/threads/threads.h"
#include "core/libraries/kernel/thread_management.h"
#include "core/libraries/libs.h"
namespace Libraries::Kernel {
extern PThreadCxt* g_pthread_cxt;
bool PthreadKeys::CreateKey(int* key, PthreadKeyDestructor destructor) {
std::scoped_lock lk{m_mutex};
for (int index = 0; index < 256; index++) {
if (!m_keys[index].used) {
*key = index;
m_keys[index].used = true;
m_keys[index].destructor = destructor;
m_keys[index].specific_values.clear();
return true;
}
}
return false;
}
bool PthreadKeys::GetKey(int key, int thread_id, void** data) {
std::scoped_lock lk{m_mutex};
if (key < 0 || key >= 256 || !m_keys[key].used) {
return false;
}
for (auto& v : m_keys[key].specific_values) {
if (v.thread_id == thread_id) {
*data = v.data;
return true;
}
}
*data = nullptr;
return true;
}
bool PthreadKeys::SetKey(int key, int thread_id, void* data) {
std::scoped_lock lk{m_mutex};
if (key < 0 || key >= 256 || !m_keys[key].used) {
return false;
}
for (auto& v : m_keys[key].specific_values) {
if (v.thread_id == thread_id) {
v.data = data;
return true;
}
}
Map keymap = {thread_id, data};
m_keys[key].specific_values.push_back(keymap);
return true;
}
int PS4_SYSV_ABI scePthreadKeyCreate(OrbisPthreadKey* key, PthreadKeyDestructor destructor) {
if (key == nullptr) {
return ORBIS_KERNEL_ERROR_EINVAL;
}
if (!g_pthread_cxt->getPthreadKeys()->CreateKey(key, destructor)) {
return ORBIS_KERNEL_ERROR_EAGAIN;
int result = pthread_key_create(key, nullptr);
if (destructor) {
auto thread = scePthreadSelf();
thread->key_destructors.emplace_back(*key, destructor);
}
return ORBIS_OK;
if (result != 0) {
LOG_ERROR(Kernel_Pthread, "scePthreadKeyCreate: error = {}", result);
result += ORBIS_KERNEL_ERROR_UNKNOWN;
}
return result;
}
void* PS4_SYSV_ABI scePthreadGetspecific(OrbisPthreadKey key) {
auto id = std::this_thread::get_id();
int thread_id = *(unsigned*)&id;
void* value = nullptr;
if (!g_pthread_cxt->getPthreadKeys()->GetKey(key, thread_id, &value)) {
return nullptr;
}
return value;
return pthread_getspecific(key);
}
int PS4_SYSV_ABI scePthreadSetspecific(OrbisPthreadKey key, /* const*/ void* value) {
auto id = std::this_thread::get_id();
int thread_id = *(unsigned*)&id;
if (!g_pthread_cxt->getPthreadKeys()->SetKey(key, thread_id, value)) {
return ORBIS_KERNEL_ERROR_EINVAL;
int result = pthread_setspecific(key, value);
if (result != 0) {
LOG_ERROR(Kernel_Pthread, "scePthreadSetspecific: error = {}", result);
result += ORBIS_KERNEL_ERROR_UNKNOWN;
}
return result;
}
return ORBIS_OK;
void KeySymbolsRegister(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("geDaqgH9lTg", "libkernel", 1, "libkernel", 1, 1, scePthreadKeyCreate);
LIB_FUNCTION("eoht7mQOCmo", "libkernel", 1, "libkernel", 1, 1, scePthreadGetspecific);
LIB_FUNCTION("+BzXYkqYeLE", "libkernel", 1, "libkernel", 1, 1, scePthreadSetspecific);
}
} // namespace Libraries::Kernel

View file

@ -15,5 +15,6 @@ int PS4_SYSV_ABI scePthreadRwlockattrInit(OrbisPthreadRwlockattr* attr);
void SemaphoreSymbolsRegister(Core::Loader::SymbolsResolver* sym);
void RwlockSymbolsRegister(Core::Loader::SymbolsResolver* sym);
void KeySymbolsRegister(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::Kernel

View file

@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <sys/mman.h>
#include "common/assert.h"
#include "common/debug.h"
#include "common/thread.h"