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:
commit
abd73fbc0d
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue