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. --- mingw-w64-libraries/winpthreads/src/cond.c | 46 +++++++++++++++++----- 1 file changed, 37 insertions(+), 9 deletions(-)
diff --git a/mingw-w64-libraries/winpthreads/src/cond.c b/mingw-w64-libraries/winpthreads/src/cond.c index cd12c8b..725622d 100644 --- a/mingw-w64-libraries/winpthreads/src/cond.c +++ b/mingw-w64-libraries/winpthreads/src/cond.c @@ -431,9 +431,24 @@ pthread_cond_wait (pthread_cond_t *c, pthread_mutex_t *external_mutex) } else if (_c->valid != (unsigned int)LIFE_COND) return EINVAL; - EnterCriticalSection (&_c->waiters_count_lock_); +tryagain: r = do_sema_b_wait (_c->sema_b, 0, INFINITE,&_c->waiters_b_lock_,&_c->value_b); + if (r != 0) + return r; + + 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); + if (r != 0) + return r; ch.c = _c; ch.r = &r; @@ -479,22 +494,35 @@ pthread_cond_timedwait_impl (pthread_cond_t *c, pthread_mutex_t *external_mutex, dwr = dwMilliSecs(_pthread_time_in_ms_from_timespec(t)); } - EnterCriticalSection (&_c->waiters_count_lock_); +tryagain: r = do_sema_b_wait (_c->sema_b, 0, INFINITE,&_c->waiters_b_lock_,&_c->value_b); + if (r != 0) + return r; + + 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); + if (r != 0) + return r; ch.c = _c; ch.r = &r; ch.external_mutex = external_mutex; - { - pthread_cleanup_push(cleanup_wait, (void *) &ch); - r = pthread_mutex_unlock(external_mutex); - if (!r) - r = do_sema_b_wait (_c->sema_q, 0, dwr,&_c->waiters_q_lock_,&_c->value_q); + pthread_cleanup_push(cleanup_wait, (void *) &ch); + r = pthread_mutex_unlock(external_mutex); + if (!r) + r = do_sema_b_wait (_c->sema_q, 0, dwr,&_c->waiters_q_lock_,&_c->value_q); + pthread_cleanup_pop(1); - pthread_cleanup_pop(1); - } return r; } -- 2.22.0 _______________________________________________ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public