pthread: fix deadlock in pthread_rwlock_*

Properly initialize and reset the _owner member, otherwise
correlating the unlock operation with the respective read/write
lock does not work.

Move locking the _nbr_mutex in the unlock operation after the
owner check. Otherwise, a reader holding that mutex and waiting
for the write lock would deadlock a writer trying to unlock the
_global_mutex.

Ref. Componolit/componolit#86
Ref. #2656
Fixes #2832
This commit is contained in:
Alexander Senier 2018-04-09 07:13:17 +02:00 committed by Christian Helmuth
parent 230ed1de37
commit 43faf63fde

View File

@ -38,7 +38,7 @@ extern "C" {
{
private:
Genode::Thread *_owner;
Genode::Thread *_owner = nullptr;
Genode::Lock _nbr_mutex {};
Genode::Lock _global_mutex {};
int _nbr = 0;
@ -51,6 +51,7 @@ extern "C" {
++_nbr;
if (_nbr == 1) {
_global_mutex.lock();
_owner = nullptr;
}
}
@ -62,12 +63,12 @@ extern "C" {
int unlock()
{
Genode::Lock_guard<Genode::Lock> guard(_nbr_mutex);
/* Read lock */
if (_owner == nullptr) {
Genode::Lock_guard<Genode::Lock> guard(_nbr_mutex);
_nbr--;
if (_nbr == 0) {
_owner = nullptr;
_global_mutex.unlock();
}
return 0;
@ -80,6 +81,7 @@ extern "C" {
};
/* Write lock owned by us */
_owner = nullptr;
_global_mutex.unlock();
return 0;
}