-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
musl: backport patches to fix pthread_cond_wait with PI mutex https:/…
…/github.com/pulseaudio/pulseaudio/blob/master/src/pulsecore/mutex-posix.c#L55 https://github.com/pulseaudio/pulseaudio/blob/master/src/pulse/thread-mainloop.c#L118 pulseaudio/pulseaudio@413a8f8 pulseaudio uses a prio-inheriting mutex since the above revision that is paised with a condition variable; the behavior of this was broken in musl until the above patches, which would result in pulseaudio deadlocking with gstreamer pulsesink (most often with webkit) and possibly other things. Fixes void-linux/void-packages#15631 void-linux/void-packages@53d00ff
- Loading branch information
Showing
4 changed files
with
133 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
From 2d0bbe6c788938d1332609c014eeebc1dff966ac Mon Sep 17 00:00:00 2001 | ||
From: Rich Felker <dalias@aerifal.cx> | ||
Date: Mon, 26 Oct 2020 15:56:25 -0400 | ||
Subject: fix pthread_cond_wait paired with with priority-inheritance mutex | ||
|
||
pthread_cond_wait arranged for requeued waiters to wake when the mutex | ||
is unlocked by temporarily adjusting the mutex's waiter count. commit | ||
54ca677983d47529bab8752315ac1a2b49888870 broke this when introducing | ||
PI mutexes by repurposing the waiter count field of the mutex | ||
structure. since then, for PI mutexes, the waiter count adjustment was | ||
misinterpreted by the mutex locking code as indicating that the mutex | ||
is non a non-recoverable state. | ||
|
||
it would be possible to special-case PI mutexes here, but instead just | ||
drop all adjustment of the waiters count, and instead use the lock | ||
word waiters bit for all mutex types. since the mutex is either held | ||
by the caller or in unrecoverable state at the time the bit is set, it | ||
will necessarily still be set at the time of any subsequent valid | ||
unlock operation, and this will produce the desired effect of waking | ||
the next waiter. | ||
|
||
if waiter counts are entirely dropped at some point in the future this | ||
code should still work without modification. | ||
--- | ||
src/thread/pthread_cond_timedwait.c | 11 +++++------ | ||
1 file changed, 5 insertions(+), 6 deletions(-) | ||
|
||
(limited to 'src/thread/pthread_cond_timedwait.c') | ||
|
||
diff --git a/src/thread/pthread_cond_timedwait.c b/src/thread/pthread_cond_timedwait.c | ||
index d1501240..f5f37af1 100644 | ||
--- a/src/thread/pthread_cond_timedwait.c | ||
+++ b/src/thread/pthread_cond_timedwait.c | ||
@@ -146,14 +146,13 @@ relock: | ||
|
||
if (oldstate == WAITING) goto done; | ||
|
||
- if (!node.next) a_inc(&m->_m_waiters); | ||
- | ||
/* Unlock the barrier that's holding back the next waiter, and | ||
* either wake it or requeue it to the mutex. */ | ||
- if (node.prev) | ||
- unlock_requeue(&node.prev->barrier, &m->_m_lock, m->_m_type & 128); | ||
- else | ||
- a_dec(&m->_m_waiters); | ||
+ if (node.prev) { | ||
+ int val = m->_m_lock; | ||
+ if (val>0) a_cas(&m->_m_lock, val, val|0x80000000); | ||
+ unlock_requeue(&node.prev->barrier, &m->_m_lock, m->_m_type & (8|128)); | ||
+ } | ||
|
||
/* Since a signal was consumed, cancellation is not permitted. */ | ||
if (e == ECANCELED) e = 0; | ||
-- | ||
cgit v1.2.1 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
From 27b2fc9d6db956359727a66c262f1e69995660aa Mon Sep 17 00:00:00 2001 | ||
From: Rich Felker <dalias@aerifal.cx> | ||
Date: Fri, 30 Oct 2020 11:21:06 -0400 | ||
Subject: fix missing-wake regression in pthread_cond_wait | ||
|
||
the reasoning in commit 2d0bbe6c788938d1332609c014eeebc1dff966ac was | ||
not entirely correct. while it's true that setting the waiters flag | ||
ensures that the next unlock will perform a wake, it's possible that | ||
the wake is consumed by a mutex waiter that has no relationship with | ||
the condvar wait queue being processed, which then takes the mutex. | ||
when that thread subsequently unlocks, it sees no waiters, and leaves | ||
the rest of the condvar queue stuck. | ||
|
||
bring back the waiter count adjustment, but skip it for PI mutexes, | ||
for which a successful lock-after-waiting always sets the waiters bit. | ||
if future changes are made to bring this same waiters-bit contract to | ||
all lock types, this can be reverted. | ||
--- | ||
src/thread/pthread_cond_timedwait.c | 5 +++++ | ||
1 file changed, 5 insertions(+) | ||
|
||
(limited to 'src/thread/pthread_cond_timedwait.c') | ||
|
||
diff --git a/src/thread/pthread_cond_timedwait.c b/src/thread/pthread_cond_timedwait.c | ||
index f5f37af1..a0cd4904 100644 | ||
--- a/src/thread/pthread_cond_timedwait.c | ||
+++ b/src/thread/pthread_cond_timedwait.c | ||
@@ -146,12 +146,17 @@ relock: | ||
|
||
if (oldstate == WAITING) goto done; | ||
|
||
+ if (!node.next && !(m->_m_type & 8)) | ||
+ a_inc(&m->_m_waiters); | ||
+ | ||
/* Unlock the barrier that's holding back the next waiter, and | ||
* either wake it or requeue it to the mutex. */ | ||
if (node.prev) { | ||
int val = m->_m_lock; | ||
if (val>0) a_cas(&m->_m_lock, val, val|0x80000000); | ||
unlock_requeue(&node.prev->barrier, &m->_m_lock, m->_m_type & (8|128)); | ||
+ } else if (!!(m->_m_type & 8)) { | ||
+ a_dec(&m->_m_waiters); | ||
} | ||
|
||
/* Since a signal was consumed, cancellation is not permitted. */ | ||
-- | ||
cgit v1.2.1 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
From d91a6cf6e369a79587c5665fce9635e5634ca201 Mon Sep 17 00:00:00 2001 | ||
From: Rich Felker <dalias@aerifal.cx> | ||
Date: Fri, 30 Oct 2020 16:50:08 -0400 | ||
Subject: fix erroneous pthread_cond_wait mutex waiter count logic due to typo | ||
|
||
introduced in commit 27b2fc9d6db956359727a66c262f1e69995660aa. | ||
--- | ||
src/thread/pthread_cond_timedwait.c | 2 +- | ||
1 file changed, 1 insertion(+), 1 deletion(-) | ||
|
||
(limited to 'src/thread/pthread_cond_timedwait.c') | ||
|
||
diff --git a/src/thread/pthread_cond_timedwait.c b/src/thread/pthread_cond_timedwait.c | ||
index a0cd4904..6b761455 100644 | ||
--- a/src/thread/pthread_cond_timedwait.c | ||
+++ b/src/thread/pthread_cond_timedwait.c | ||
@@ -155,7 +155,7 @@ relock: | ||
int val = m->_m_lock; | ||
if (val>0) a_cas(&m->_m_lock, val, val|0x80000000); | ||
unlock_requeue(&node.prev->barrier, &m->_m_lock, m->_m_type & (8|128)); | ||
- } else if (!!(m->_m_type & 8)) { | ||
+ } else if (!(m->_m_type & 8)) { | ||
a_dec(&m->_m_waiters); | ||
} | ||
|
||
-- | ||
cgit v1.2.1 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters