new internal locking primitive; drop spinlocks
we use priority inheritance futexes if possible so that the library cannot hit internal priority inversion deadlocks in the presence of realtime priority scheduling (full support to be added later).
This commit is contained in:
parent
1b0ce9af6d
commit
f34d0ea511
2 changed files with 29 additions and 7 deletions
|
|
@ -1,11 +1,32 @@
|
|||
#include "pthread_impl.h"
|
||||
|
||||
void __lock_2(volatile int *l)
|
||||
{
|
||||
if (!__syscall(SYS_futex, l, FUTEX_LOCK_PI, 0, 0))
|
||||
return;
|
||||
int old, tid = __pthread_self()->tid;
|
||||
while ((old = a_cas(l, 0, tid))) {
|
||||
a_cas(l, old, old|INT_MIN);
|
||||
__syscall(SYS_futex, l, FUTEX_WAIT, old|INT_MIN, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void __lock(volatile int *l)
|
||||
{
|
||||
int spins=10000;
|
||||
/* Do not use futexes because we insist that unlocking is a simple
|
||||
* assignment to optimize non-pathological code with no contention. */
|
||||
while (a_swap(l, 1))
|
||||
if (spins) spins--, a_spin();
|
||||
else __syscall(SYS_sched_yield);
|
||||
if (a_cas(l, 0, __pthread_self()->tid)) __lock_2(l);
|
||||
}
|
||||
|
||||
void __unlock_2(volatile int *l)
|
||||
{
|
||||
if (__syscall(SYS_futex, l, FUTEX_UNLOCK_PI)) {
|
||||
*l = 0;
|
||||
__syscall(SYS_futex, l, FUTEX_WAKE, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void __unlock(volatile int *l)
|
||||
{
|
||||
int old = *l;
|
||||
if (!(old & INT_MIN) && a_cas(l, old, 0)==old) return;
|
||||
__unlock_2(l);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue