draft pthreads keys implementation

This commit is contained in:
georgemoralis 2024-06-13 14:36:29 +03:00
parent 9ccc8786eb
commit a660a94f3b
4 changed files with 142 additions and 0 deletions

View file

@ -107,6 +107,7 @@ set(KERNEL_LIB
src/core/libraries/kernel/event_flag/event_flag_obj.h
src/core/libraries/kernel/threads/rwlock.cpp
src/core/libraries/kernel/threads/semaphore.cpp
src/core/libraries/kernel/threads/keys.cpp
src/core/libraries/kernel/threads/threads.h
src/core/libraries/kernel/cpu_management.cpp
src/core/libraries/kernel/cpu_management.h

View file

@ -41,6 +41,7 @@ void init_pthreads() {
scePthreadRwlockattrInit(&default_rwattr);
g_pthread_cxt->setDefaultRwattr(default_rwattr);
g_pthread_cxt->setPthreadKeys(new PthreadKeys);
g_pthread_cxt->SetPthreadPool(new PThreadPool);
}
@ -1323,4 +1324,6 @@ void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
SemaphoreSymbolsRegister(sym);
}
} // namespace Libraries::Kernel

View file

@ -10,6 +10,7 @@
#include <pthread.h>
#include <sched.h>
#include "common/types.h"
#include <mutex>
namespace Core::Loader {
class SymbolsResolver;
@ -28,6 +29,7 @@ struct PthreadCondInternal;
struct PthreadCondAttrInternal;
struct PthreadRwInternal;
struct PthreadRwLockAttrInernal;
class PthreadKeys;
using SceKernelSchedParam = ::sched_param;
using ScePthread = PthreadInternal*;
@ -38,6 +40,9 @@ using ScePthreadCond = PthreadCondInternal*;
using ScePthreadCondattr = PthreadCondAttrInternal*;
using OrbisPthreadRwlock = PthreadRwInternal*;
using OrbisPthreadRwlockattr = PthreadRwLockAttrInernal*;
using OrbisPthreadKey = int;
using PthreadKeyDestructor = PS4_SYSV_ABI void (*)(void*);
using pthreadEntryFunc = PS4_SYSV_ABI void* (*)(void*);
@ -106,6 +111,30 @@ private:
std::mutex m_mutex;
};
class PthreadKeys {
public:
PthreadKeys() {}
virtual ~PthreadKeys() {}
bool CreateKey(int* key, PthreadKeyDestructor destructor);
bool GetKey(int key, int thread_id, void** data);
bool SetKey(int key, int thread_id, void* data);
private:
struct Map {
int thread_id = -1;
void* data = nullptr;
};
struct Key {
bool used = false;
PthreadKeyDestructor destructor = nullptr;
std::vector<Map> specific_values;
};
std::mutex m_mutex;
Key m_keys[256];
};
class PThreadCxt {
public:
ScePthreadMutexattr* getDefaultMutexattr() {
@ -138,6 +167,12 @@ public:
void setDefaultRwattr(OrbisPthreadRwlockattr attr) {
m_default_Rwattr = attr;
}
PthreadKeys* getPthreadKeys() {
return m_pthread_keys;
}
void setPthreadKeys(PthreadKeys* keys) {
m_pthread_keys = keys;
}
private:
ScePthreadMutexattr m_default_mutexattr = nullptr;
@ -145,6 +180,7 @@ private:
ScePthreadAttr m_default_attr = nullptr;
PThreadPool* m_pthread_pool = nullptr;
OrbisPthreadRwlockattr m_default_Rwattr = nullptr;
PthreadKeys* m_pthread_keys = nullptr;
};
void init_pthreads();

View file

@ -0,0 +1,102 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/logging/log.h"
#include "core/libraries/error_codes.h"
#include "core/libraries/libs.h"
#include "threads.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 SCE_KERNEL_ERROR_EINVAL;
}
if (!g_pthread_cxt->getPthreadKeys()->CreateKey(key, destructor)) {
return SCE_KERNEL_ERROR_EAGAIN;
}
return SCE_OK;
}
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;
}
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 SCE_KERNEL_ERROR_EINVAL;
}
return SCE_OK;
}
} // namespace Libraries::Kernel