mirror of https://github.com/RPCS3/rpcs3.git
atomic.cpp: fix race in cond_id_lock()
This commit is contained in:
parent
9a93b150f0
commit
0a5ea859ea
|
@ -665,10 +665,17 @@ static void cond_free(u32 cond_id, u32 tls_slot = -1)
|
||||||
|
|
||||||
static cond_handle* cond_id_lock(u32 cond_id, u128 mask, uptr iptr = 0)
|
static cond_handle* cond_id_lock(u32 cond_id, u128 mask, uptr iptr = 0)
|
||||||
{
|
{
|
||||||
if (cond_id - 1 < u16{umax})
|
bool did_ref = false;
|
||||||
{
|
|
||||||
const auto cond = s_cond_list + cond_id;
|
|
||||||
|
|
||||||
|
if (cond_id - 1 >= u16{umax})
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto cond = s_cond_list + cond_id;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
const auto [old, ok] = cond->ptr_ref.fetch_op([&](u64& val)
|
const auto [old, ok] = cond->ptr_ref.fetch_op([&](u64& val)
|
||||||
{
|
{
|
||||||
if (!val || (val & s_ref_mask) == s_ref_mask)
|
if (!val || (val & s_ref_mask) == s_ref_mask)
|
||||||
|
@ -695,12 +702,23 @@ static cond_handle* cond_id_lock(u32 cond_id, u128 mask, uptr iptr = 0)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
val++;
|
if (!did_ref)
|
||||||
|
{
|
||||||
|
val++;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (ok)
|
if (ok)
|
||||||
{
|
{
|
||||||
|
// Check other fields again
|
||||||
|
if (const u32 sync_val = cond->sync; sync_val == 0 || sync_val == 3 || (cond->size && !(mask & cond->mask)))
|
||||||
|
{
|
||||||
|
did_ref = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
return cond;
|
return cond;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -708,6 +726,13 @@ static cond_handle* cond_id_lock(u32 cond_id, u128 mask, uptr iptr = 0)
|
||||||
{
|
{
|
||||||
fmt::throw_exception("Reference count limit (131071) reached in an atomic notifier.");
|
fmt::throw_exception("Reference count limit (131071) reached in an atomic notifier.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (did_ref)
|
||||||
|
{
|
||||||
|
cond_free(cond_id, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
Loading…
Reference in New Issue