From 602a76fc26f9ddf755a61fadc5840d3d8dda07c1 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 11 Oct 2026 20:57:22 +0000 Subject: [PATCH] fix(libkernel): let pthread_barrier_destroy wait for released waiters Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Ha6Tsy62AFUyp9a5Mf7vjA --- .../libs/prx/libkernel/Pthread/Posix/Barrier.cpp | 7 ++++--- core/libs/tests/GuestPthreadBarrier.cpp | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/core/libs/prx/libkernel/Pthread/Posix/Barrier.cpp b/core/libs/prx/libkernel/Pthread/Posix/Barrier.cpp index 140b6900e..4d03696ff 100644 --- a/core/libs/prx/libkernel/Pthread/Posix/Barrier.cpp +++ b/core/libs/prx/libkernel/Pthread/Posix/Barrier.cpp @@ -86,7 +86,7 @@ int APS5_VABI pthread_barrier_wait_nid_postfix(PthreadBarrierPrivate** barrier) return -1; } value.changed.wait(lock, [&] { return value.generation != generation; }); - --value.active; + if (--value.active == 0) value.changed.notify_all(); return 0; } @@ -94,8 +94,9 @@ int APS5_VABI pthread_barrier_destroy_nid_postfix(PthreadBarrierPrivate** barrie if (!barrier || !*barrier) return 22; auto* value = *barrier; { - std::lock_guard lock(value->mutex); - if (value->active != 0) return 16; + std::unique_lock lock(value->mutex); + if (value->arrived != 0) return 16; + value->changed.wait(lock, [&] { return value->active == 0; }); } delete value; *barrier = nullptr; diff --git a/core/libs/tests/GuestPthreadBarrier.cpp b/core/libs/tests/GuestPthreadBarrier.cpp index 64d67e201..6686ebc01 100644 --- a/core/libs/tests/GuestPthreadBarrier.cpp +++ b/core/libs/tests/GuestPthreadBarrier.cpp @@ -42,6 +42,13 @@ static void* APS5_VABI Waiter(void* arg) { return nullptr; } +static void* APS5_VABI DestroyingWaiter(void* arg) { + auto& context = *static_cast(arg); + if (pthread_barrier_wait_nid_postfix(&context.barrier) == BARRIER_SERIAL_THREAD) + context.serial = pthread_barrier_destroy_nid_postfix(&context.barrier) == 0 && context.barrier == nullptr ? 1 : -1; + return nullptr; +} + static void RunWaiters(Context& context) { std::array threads{}; for (auto& thread : threads) Require(scePthreadCreate(&thread, nullptr, Waiter, &context, nullptr) == 0); @@ -101,6 +108,15 @@ int main() { RunWaiters(withoutAttr); Require(pthread_barrier_destroy_nid_postfix(&withoutAttr.barrier) == 0); + for (int round = 0; round < 50; ++round) { + Context destroyed; + Require(pthread_barrier_init_nid_postfix(&destroyed.barrier, nullptr, WAITERS) == 0); + std::array threads{}; + for (auto& thread : threads) Require(scePthreadCreate(&thread, nullptr, DestroyingWaiter, &destroyed, nullptr) == 0); + for (auto& thread : threads) Require(scePthreadJoin(thread, nullptr) == 0); + Require(destroyed.serial == 1); + } + GuestBarrier* single = nullptr; Require(pthread_barrierattr_init_nid_postfix(&attr) == 0); Require(pthread_barrier_init_nid_postfix(&single, &attr, 1) == 0);