2011-12-26 20:33:09 +04:00
|
|
|
#ifndef CR_LOCK_H_
|
|
|
|
#define CR_LOCK_H_
|
|
|
|
|
|
|
|
#include <linux/futex.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
#include "types.h"
|
|
|
|
#include "atomic.h"
|
|
|
|
#include "syscall.h"
|
|
|
|
#include "util.h"
|
|
|
|
|
2012-01-02 20:29:02 +04:00
|
|
|
/*
|
|
|
|
* Init futex @v value
|
|
|
|
*/
|
|
|
|
static always_inline void cr_wait_init(u32 *v)
|
|
|
|
{
|
|
|
|
u32 val = 0;
|
|
|
|
atomic_set(v, val);
|
|
|
|
}
|
|
|
|
|
2011-12-26 20:33:09 +04:00
|
|
|
/*
|
|
|
|
* Set futex @v value to @val and wake up all waiters
|
|
|
|
*/
|
|
|
|
static always_inline void cr_wait_set(u32 *v, u32 val)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
atomic_set(v, val);
|
|
|
|
|
|
|
|
ret = sys_futex(v, FUTEX_WAKE, INT_MAX, NULL, NULL, 0);
|
|
|
|
BUG_ON(ret < 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Decrement futex @v value to @val and wake up all waiters
|
|
|
|
*/
|
|
|
|
static always_inline void cr_wait_dec(u32 *v)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
atomic_dec(v);
|
|
|
|
|
|
|
|
ret = sys_futex(v, FUTEX_WAKE, INT_MAX, NULL, NULL, 0);
|
|
|
|
BUG_ON(ret < 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Wait until futex @v value become @val
|
|
|
|
*/
|
|
|
|
static always_inline void cr_wait_until(u32 *v, u32 val)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
u32 tmp;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
tmp = *v;
|
|
|
|
if (tmp == val)
|
|
|
|
break;
|
|
|
|
ret = sys_futex(v, FUTEX_WAIT, tmp, NULL, NULL, 0);
|
|
|
|
BUG_ON(ret < 0 && ret != -EWOULDBLOCK);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Wait while futex @v value is @val
|
|
|
|
*/
|
|
|
|
static always_inline void cr_wait_while(u32 *v, u32 val)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
while (*v == val) {
|
|
|
|
ret = sys_futex(v, FUTEX_WAIT, val, NULL, NULL, 0);
|
|
|
|
BUG_ON(ret < 0 && ret != -EWOULDBLOCK);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Init @mutex value
|
|
|
|
*/
|
|
|
|
static void always_inline cr_mutex_init(u32 *mutex)
|
|
|
|
{
|
|
|
|
u32 c = 0;
|
|
|
|
atomic_set(mutex, c);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Lock @mutex
|
|
|
|
*/
|
|
|
|
static void always_inline cr_mutex_lock(u32 *mutex)
|
|
|
|
{
|
|
|
|
u32 c;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
while ((c = atomic_inc(mutex))) {
|
|
|
|
ret = sys_futex(mutex, FUTEX_WAIT, c + 1, NULL, NULL, 0);
|
|
|
|
BUG_ON(ret < 0 && ret != -EWOULDBLOCK);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Unlock @mutex
|
|
|
|
*/
|
|
|
|
static void always_inline cr_mutex_unlock(u32 *mutex)
|
|
|
|
{
|
|
|
|
u32 c = 0;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
atomic_set(mutex, c);
|
|
|
|
|
|
|
|
ret = sys_futex(mutex, FUTEX_WAKE, 1, NULL, NULL, 0);
|
|
|
|
BUG_ON(ret < 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* CR_LOCK_H_ */
|