From 43faf63fded4ee6e798578bb473d6ae699021c78 Mon Sep 17 00:00:00 2001 From: Alexander Senier Date: Mon, 9 Apr 2018 07:13:17 +0200 Subject: [PATCH] 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 --- repos/libports/src/lib/pthread/rwlock.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/repos/libports/src/lib/pthread/rwlock.cc b/repos/libports/src/lib/pthread/rwlock.cc index 0fd961174d..102939337e 100644 --- a/repos/libports/src/lib/pthread/rwlock.cc +++ b/repos/libports/src/lib/pthread/rwlock.cc @@ -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 guard(_nbr_mutex); - /* Read lock */ if (_owner == nullptr) { + Genode::Lock_guard 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; }