diff options
| -rw-r--r-- | src/internal/libc.h | 3 | ||||
| -rw-r--r-- | src/thread/__lock.c | 33 | 
2 files changed, 29 insertions, 7 deletions
diff --git a/src/internal/libc.h b/src/internal/libc.h index 39a18658..d6797f90 100644 --- a/src/internal/libc.h +++ b/src/internal/libc.h @@ -45,10 +45,11 @@ extern struct __libc *__libc_loc(void) __attribute__((const));  /* Designed to avoid any overhead in non-threaded processes */  void __lock(volatile int *); +void __unlock(volatile int *);  int __lockfile(FILE *);  void __unlockfile(FILE *);  #define LOCK(x) (libc.threads_minus_1 ? (__lock(x),1) : ((void)(x),1)) -#define UNLOCK(x) (*(volatile int *)(x)=0) +#define UNLOCK(x) (libc.threads_minus_1 ? (__unlock(x),1) : ((void)(x),1))  void __synccall(void (*)(void *), void *);  void __synccall_wait(void); diff --git a/src/thread/__lock.c b/src/thread/__lock.c index d1717956..d1734096 100644 --- a/src/thread/__lock.c +++ b/src/thread/__lock.c @@ -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);  }  | 
