Merge pull request #1922 from rmz-24/feat/libkernel-pthread-getaffinity-np

feat(libkernel): implement pthread_getaffinity_np
This commit is contained in:
Adrià 2026-10-11 10:32:42 +02:00 committed by GitHub
commit ccf9ff9044
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 43 additions and 0 deletions

View File

@ -9,6 +9,7 @@
#include "Common.hpp"
#include "prx/libkernel/KernelErrors.hpp"
#include <chrono>
#include <cstring>
#include <thread>
extern "C" {
@ -28,6 +29,8 @@ int APS5_VABI scePthreadGetprio(Pthread thread, int* prio);
}
static constexpr int GUEST_SCHED_FIFO = 1;
static constexpr std::size_t GUEST_CPUSET_BYTES = 32;
static constexpr int GUEST_ERANGE = 34;
extern "C" {
int* APS5_VABI __error_nid_postfix();
@ -116,6 +119,18 @@ int APS5_VABI pthread_getschedparam_nid_postfix(Pthread thread, int* policy, Ker
return PosixThread::ToErrno(scePthreadGetprio(thread, &param->sched_priority));
}
int APS5_VABI pthread_getaffinity_np_nid_postfix(Pthread thread, std::size_t cpusetSize, void* cpuset) {
if (!thread) return PosixThread::GUEST_EINVAL;
if (cpusetSize != GUEST_CPUSET_BYTES) return GUEST_ERANGE;
if (!cpuset) return PosixThread::GUEST_EFAULT;
KernelCpumask mask = 0;
const int result = scePthreadGetaffinity(thread, &mask);
if (result != 0) return PosixThread::ToErrno(result);
std::memset(cpuset, 0, GUEST_CPUSET_BYTES);
std::memcpy(cpuset, &mask, sizeof(mask));
return 0;
}
int APS5_VABI pthread_join_nid_postfix(Pthread thread, void** value) {
return PosixThread::ToErrno(scePthreadJoin(thread, value));
}

View File

@ -2,6 +2,7 @@
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <future>
extern "C" {
@ -18,6 +19,8 @@ int APS5_VABI cpuset_getaffinity_nid_postfix(int level, int which, std::int64_t
int APS5_VABI cpuset_setaffinity_nid_postfix(int level, int which, std::int64_t id, std::size_t size, const void* mask);
int APS5_VABI getpid_nid_postfix(void);
int* APS5_VABI __error_nid_postfix();
Pthread APS5_VABI pthread_self_nid_postfix(void);
int APS5_VABI pthread_getaffinity_np_nid_postfix(Pthread thread, std::size_t cpusetSize, void* cpuset);
}
static constexpr int SCE_OK = 0;
@ -25,6 +28,22 @@ static constexpr int PS5_LOGICAL_CPUS = 16;
static void Require(bool value) { if (!value) std::abort(); }
static constexpr std::size_t GUEST_CPUSET_BYTES = 32;
static constexpr int GUEST_EINVAL = 22;
static constexpr int GUEST_EFAULT = 14;
static constexpr int GUEST_ERANGE = 34;
static KernelCpumask ReadCpuset(Pthread thread) {
std::uint8_t cpuset[GUEST_CPUSET_BYTES + 8];
std::memset(cpuset, 0xAB, sizeof(cpuset));
Require(pthread_getaffinity_np_nid_postfix(thread, GUEST_CPUSET_BYTES, cpuset) == 0);
for (std::size_t i = sizeof(KernelCpumask); i < GUEST_CPUSET_BYTES; ++i) Require(cpuset[i] == 0);
for (std::size_t i = GUEST_CPUSET_BYTES; i < sizeof(cpuset); ++i) Require(cpuset[i] == 0xAB);
KernelCpumask mask = 0;
std::memcpy(&mask, cpuset, sizeof(mask));
return mask;
}
static void* APS5_VABI Worker(void* arg) {
static_cast<std::future<void>*>(arg)->get();
return nullptr;
@ -102,6 +121,7 @@ int main() {
Require(scePthreadSetaffinity(thread, cpu) == SCE_OK);
Require(scePthreadGetaffinity(thread, &threadAffinity) == SCE_OK);
Require(threadAffinity == cpu);
Require(ReadCpuset(thread) == cpu);
}
release.set_value();
Require(scePthreadJoin(thread, nullptr) == SCE_OK);
@ -143,4 +163,12 @@ int main() {
hold.set_value();
Require(scePthreadJoin(bystander, nullptr) == SCE_OK);
Require(scePthreadAttrDestroy(&attr) == SCE_OK);
Require(ReadCpuset(pthread_self_nid_postfix()) == available);
std::uint8_t rawSet[GUEST_CPUSET_BYTES]{};
for (const std::size_t size : {std::size_t{0}, std::size_t{8}, std::size_t{31}, std::size_t{33}, std::size_t{64}})
Require(pthread_getaffinity_np_nid_postfix(pthread_self_nid_postfix(), size, rawSet) == GUEST_ERANGE);
Require(pthread_getaffinity_np_nid_postfix(nullptr, GUEST_CPUSET_BYTES, rawSet) == GUEST_EINVAL);
Require(pthread_getaffinity_np_nid_postfix(nullptr, 0, rawSet) == GUEST_EINVAL);
Require(pthread_getaffinity_np_nid_postfix(pthread_self_nid_postfix(), GUEST_CPUSET_BYTES, nullptr) == GUEST_EFAULT);
}