Merge pull request #4002 from zmeizy/claude/barrier-destroy-after-release

fix(libkernel): let pthread_barrier_destroy wait for released waiters
This commit is contained in:
Dean 2026-10-12 18:19:21 +13:00 committed by GitHub
commit abd73fbc0d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 20 additions and 3 deletions

View File

@ -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;

View File

@ -42,6 +42,13 @@ static void* APS5_VABI Waiter(void* arg) {
return nullptr;
}
static void* APS5_VABI DestroyingWaiter(void* arg) {
auto& context = *static_cast<Context*>(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<Pthread, WAITERS> 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<Pthread, WAITERS> 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);