somehow working scePthreadCreate
This commit is contained in:
parent
c832e3831a
commit
121759d836
|
@ -6,6 +6,7 @@
|
|||
#include "core/hle/error_codes.h"
|
||||
#include "core/hle/libraries/libkernel/thread_management.h"
|
||||
#include "core/hle/libraries/libs.h"
|
||||
#include <mutex>
|
||||
|
||||
namespace Core::Libraries::LibKernel {
|
||||
|
||||
|
@ -22,6 +23,12 @@ void init_pthreads() {
|
|||
ScePthreadCondattr default_condattr = nullptr;
|
||||
scePthreadCondattrInit(&default_condattr);
|
||||
g_pthread_cxt->setDefaultCondattr(default_condattr);
|
||||
// default attr init
|
||||
ScePthreadAttr default_attr = nullptr;
|
||||
scePthreadAttrInit(&default_attr);
|
||||
g_pthread_cxt->SetDefaultAttr(default_attr);
|
||||
|
||||
g_pthread_cxt->SetPthreadPool(new PThreadPool);
|
||||
}
|
||||
|
||||
void pthreadInitSelfMainThread() {
|
||||
|
@ -348,12 +355,6 @@ int PS4_SYSV_ABI scePthreadSetaffinity(ScePthread thread, const /*SceKernelCpuma
|
|||
return result;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI scePthreadCreate(ScePthread* thread, const ScePthreadAttr* attr,
|
||||
pthreadEntryFunc start_routine, void* arg, const char* name) {
|
||||
LOG_INFO(Kernel_Pthread, "(STUBBED) called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* createMutex(void* addr) {
|
||||
if (addr == nullptr || *static_cast<ScePthreadMutex*>(addr) != nullptr) {
|
||||
return addr;
|
||||
|
@ -754,6 +755,100 @@ int PS4_SYSV_ABI scePthreadAttrGet(ScePthread thread, ScePthreadAttr* attr) {
|
|||
return pthread_copy_attributes(attr, &thread->attr);
|
||||
}
|
||||
|
||||
static void cleanup_thread(void* arg) {
|
||||
auto* thread = static_cast<ScePthread>(arg);
|
||||
thread->is_almost_done = true;
|
||||
}
|
||||
|
||||
static void* run_thread(void* arg) {
|
||||
auto* thread = static_cast<ScePthread>(arg);
|
||||
void* ret = nullptr;
|
||||
g_pthread_self = thread;
|
||||
pthread_cleanup_push(cleanup_thread, thread);
|
||||
thread->is_started = true;
|
||||
ret = thread->entry(thread->arg);
|
||||
pthread_cleanup_pop(1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI scePthreadCreate(ScePthread* thread, const ScePthreadAttr* attr,
|
||||
pthreadEntryFunc start_routine, void* arg, const char* name) {
|
||||
if (thread == nullptr) {
|
||||
return SCE_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
|
||||
auto* pthread_pool = g_pthread_cxt->GetPthreadPool();
|
||||
|
||||
if (attr == nullptr) {
|
||||
attr = g_pthread_cxt->GetDefaultAttr();
|
||||
}
|
||||
|
||||
*thread = pthread_pool->Create();
|
||||
|
||||
if ((*thread)->attr != nullptr) {
|
||||
scePthreadAttrDestroy(&(*thread)->attr);
|
||||
}
|
||||
|
||||
scePthreadAttrInit(&(*thread)->attr);
|
||||
|
||||
int result = pthread_copy_attributes(&(*thread)->attr, attr);
|
||||
|
||||
if (result == 0) {
|
||||
(*thread)->name = name;
|
||||
(*thread)->entry = start_routine;
|
||||
(*thread)->arg = arg;
|
||||
(*thread)->is_almost_done = false;
|
||||
(*thread)->is_detached = (*attr)->detached;
|
||||
(*thread)->is_started = false;
|
||||
|
||||
result = pthread_create(&(*thread)->pth, &(*attr)->pth_attr, run_thread, *thread);
|
||||
}
|
||||
|
||||
if (result == 0) {
|
||||
while (!(*thread)->is_started) {
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(1000));
|
||||
}
|
||||
}
|
||||
LOG_INFO(Kernel_Pthread, "thread create name = {}",(*thread)->name);
|
||||
|
||||
switch (result) {
|
||||
case 0:
|
||||
return SCE_OK;
|
||||
case ENOMEM:
|
||||
return SCE_KERNEL_ERROR_ENOMEM;
|
||||
case EAGAIN:
|
||||
return SCE_KERNEL_ERROR_EAGAIN;
|
||||
case EDEADLK:
|
||||
return SCE_KERNEL_ERROR_EDEADLK;
|
||||
case EPERM:
|
||||
return SCE_KERNEL_ERROR_EPERM;
|
||||
default:
|
||||
return SCE_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
ScePthread PThreadPool::Create() {
|
||||
std::scoped_lock lock{m_mutex};
|
||||
|
||||
for (auto* p : m_threads) {
|
||||
if (p->is_free) {
|
||||
p->is_free = false;
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
auto* ret = new PthreadInternal{};
|
||||
|
||||
ret->is_free = false;
|
||||
ret->is_detached = false;
|
||||
ret->is_almost_done = false;
|
||||
ret->attr = nullptr;
|
||||
|
||||
m_threads.push_back(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void pthreadSymbolsRegister(Loader::SymbolsResolver* sym) {
|
||||
LIB_FUNCTION("4+h9EzwKF4I", "libkernel", 1, "libkernel", 1, 1, scePthreadAttrSetschedpolicy);
|
||||
LIB_FUNCTION("-Wreprtu0Qs", "libkernel", 1, "libkernel", 1, 1, scePthreadAttrSetdetachstate);
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#include <string>
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
|
||||
#include "common/types.h"
|
||||
|
||||
|
@ -43,6 +45,12 @@ struct PthreadInternal {
|
|||
std::string name;
|
||||
pthread_t pth;
|
||||
ScePthreadAttr attr;
|
||||
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;
|
||||
};
|
||||
|
||||
struct PthreadAttrInternal {
|
||||
|
@ -77,6 +85,17 @@ struct PthreadCondAttrInternal {
|
|||
pthread_condattr_t cond_attr;
|
||||
};
|
||||
|
||||
class PThreadPool {
|
||||
public:
|
||||
ScePthread Create();
|
||||
|
||||
void FreeDetachedThreads();
|
||||
|
||||
private:
|
||||
std::vector<ScePthread> m_threads;
|
||||
std::mutex m_mutex;
|
||||
};
|
||||
|
||||
class PThreadCxt {
|
||||
public:
|
||||
ScePthreadMutexattr* getDefaultMutexattr() {
|
||||
|
@ -91,10 +110,24 @@ public:
|
|||
void setDefaultCondattr(ScePthreadCondattr attr) {
|
||||
m_default_condattr = attr;
|
||||
}
|
||||
ScePthreadAttr* GetDefaultAttr() {
|
||||
return &m_default_attr;
|
||||
}
|
||||
void SetDefaultAttr(ScePthreadAttr attr) {
|
||||
m_default_attr = attr;
|
||||
}
|
||||
PThreadPool* GetPthreadPool() {
|
||||
return m_pthread_pool;
|
||||
}
|
||||
void SetPthreadPool(PThreadPool* pool) {
|
||||
m_pthread_pool = pool;
|
||||
}
|
||||
|
||||
private:
|
||||
ScePthreadMutexattr m_default_mutexattr = nullptr;
|
||||
ScePthreadCondattr m_default_condattr = nullptr;
|
||||
ScePthreadAttr m_default_attr = nullptr;
|
||||
PThreadPool* m_pthread_pool = nullptr;
|
||||
};
|
||||
|
||||
void init_pthreads();
|
||||
|
|
Loading…
Reference in New Issue