mirror of
https://git.code.sf.net/p/mingw-w64/mingw-w64
synced 2024-11-23 09:54:39 +08:00
Wait on sema_b again to ensure pthread_cond_wait() functions atomically as required by POSIX.
Since holding sema_b before aquiring waiters_count_lock_ can lead to deadlocks try to aquire waiters_count_lock_ opportunistically. If it fails then release sema_b and sched_yield() to give the other thread (which has aquired waiters_count_lock_ and is now waiting on sema_b) a chance to aquire sema_b before we retry the whole procedure. Signed-off-by: Liu Hao <lh_mouse@126.com>
This commit is contained in:
parent
1ebdd63cff
commit
330025c54b
@ -431,10 +431,20 @@ pthread_cond_wait (pthread_cond_t *c, pthread_mutex_t *external_mutex)
|
||||
} else if (_c->valid != (unsigned int)LIFE_COND)
|
||||
return EINVAL;
|
||||
|
||||
tryagain:
|
||||
r = do_sema_b_wait (_c->sema_b, 0, INFINITE,&_c->waiters_b_lock_,&_c->value_b);
|
||||
if (r != 0)
|
||||
return r;
|
||||
EnterCriticalSection (&_c->waiters_count_lock_);
|
||||
|
||||
if (!TryEnterCriticalSection (&_c->waiters_count_lock_))
|
||||
{
|
||||
r = do_sema_b_release (_c->sema_b, 1,&_c->waiters_b_lock_,&_c->value_b);
|
||||
if (r != 0)
|
||||
return r;
|
||||
sched_yield();
|
||||
goto tryagain;
|
||||
}
|
||||
|
||||
_c->waiters_count_++;
|
||||
LeaveCriticalSection(&_c->waiters_count_lock_);
|
||||
r = do_sema_b_release (_c->sema_b, 1,&_c->waiters_b_lock_,&_c->value_b);
|
||||
@ -485,10 +495,20 @@ pthread_cond_timedwait_impl (pthread_cond_t *c, pthread_mutex_t *external_mutex,
|
||||
dwr = dwMilliSecs(_pthread_time_in_ms_from_timespec(t));
|
||||
}
|
||||
|
||||
tryagain:
|
||||
r = do_sema_b_wait (_c->sema_b, 0, INFINITE,&_c->waiters_b_lock_,&_c->value_b);
|
||||
if (r != 0)
|
||||
return r;
|
||||
EnterCriticalSection (&_c->waiters_count_lock_);
|
||||
|
||||
if (!TryEnterCriticalSection (&_c->waiters_count_lock_))
|
||||
{
|
||||
r = do_sema_b_release (_c->sema_b, 1,&_c->waiters_b_lock_,&_c->value_b);
|
||||
if (r != 0)
|
||||
return r;
|
||||
sched_yield();
|
||||
goto tryagain;
|
||||
}
|
||||
|
||||
_c->waiters_count_++;
|
||||
LeaveCriticalSection(&_c->waiters_count_lock_);
|
||||
r = do_sema_b_release (_c->sema_b, 1,&_c->waiters_b_lock_,&_c->value_b);
|
||||
|
Loading…
Reference in New Issue
Block a user