wait: Fix a race

This commit is contained in:
plutooo 2018-12-13 01:01:42 +01:00 committed by fincs
parent eb01ccd097
commit b38983c1b7
3 changed files with 12 additions and 5 deletions

View File

@ -39,7 +39,7 @@ void _ueventTryAutoClear(UsermodeEvent* e)
bool _ueventAddListener(UsermodeEvent* e, WaiterNode* w, size_t idx, size_t* idx_out, Handle thread)
{
_waiterNodeInitialize(w, WaiterNodeType_Event, &e->waitable, thread, idx, idx_out);
_waiterNodeCreate(w, WaiterNodeType_Event, &e->waitable, thread, idx, idx_out);
mutexLock(&e->waitable.mutex);

View File

@ -73,7 +73,7 @@ u64 _utimerGetNextTick(UsermodeTimer* t)
void _utimerAddListener(UsermodeTimer* t, WaiterNode* w, size_t idx, size_t* idx_out, Handle thread)
{
_waiterNodeInitialize(w, WaiterNodeType_Timer, &t->waitable, thread, idx, idx_out);
_waiterNodeCreate(w, WaiterNodeType_Timer, &t->waitable, thread, idx, idx_out);
mutexLock(&t->waitable.mutex);
_waiterNodeAddToWaitable(w, &t->waitable);

View File

@ -20,12 +20,19 @@ static inline void _waitableSignalAllListeners(Waitable* ww)
node = node->next;
WaiterNode* w = (WaiterNode*) node;
*w->idx_out = w->idx;
svcCancelSynchronization(w->thread);
// Try to swap -1 => idx on the waiter thread.
// If another waitable signals simultaneously only one will win the race and insert its own idx.
size_t minus_one = -1;
bool sent_idx = __atomic_compare_exchange_n(
w->idx_out, &minus_one, w->idx, true, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
if (sent_idx) {
svcCancelSynchronization(w->thread);
}
}
}
static inline void _waiterNodeInitialize(
static inline void _waiterNodeCreate(
WaiterNode* w, WaiterNodeType type, Waitable* parent, Handle thread,
size_t idx, size_t* idx_out)
{