summaryrefslogtreecommitdiff
path: root/src/thread/__lock.c
blob: 5ba5dc5ee618a2fce5561f5a0f0a3e1709838719 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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|INT_MIN;
	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)
{
	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);
}