mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-04-20 19:44:46 +00:00
draft pthreads keys implementation
This commit is contained in:
parent
9ccc8786eb
commit
a660a94f3b
4 changed files with 142 additions and 0 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
102
src/core/libraries/kernel/threads/keys.cpp
Normal file
102
src/core/libraries/kernel/threads/keys.cpp
Normal 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
|
Loading…
Add table
Reference in a new issue