Files
mckernel/kernel/include/lwk/futex.h
2015-11-24 14:58:04 +09:00

111 lines
2.7 KiB
C

#ifndef _LWK_FUTEX_H
#define _LWK_FUTEX_H
/** \name Futex Commands
* @{
*/
#define FUTEX_WAIT 0
#define FUTEX_WAKE 1
#define FUTEX_CMP_REQUEUE 4
#define FUTEX_WAKE_OP 5
#define FUTEX_WAIT_BITSET 9
#define FUTEX_WAKE_BITSET 10
// @}
#define FUTEX_PRIVATE_FLAG 128
#define FUTEX_CLOCK_REALTIME 256
#define FUTEX_CMD_MASK ~(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME)
/** \name Futex Operations, used for FUTEX_WAKE_OP
* @{
*/
#define FUTEX_OP_SET 0 /* *(int *)UADDR2 = OPARG; */
#define FUTEX_OP_ADD 1 /* *(int *)UADDR2 += OPARG; */
#define FUTEX_OP_OR 2 /* *(int *)UADDR2 |= OPARG; */
#define FUTEX_OP_ANDN 3 /* *(int *)UADDR2 &= ~OPARG; */
#define FUTEX_OP_XOR 4 /* *(int *)UADDR2 ^= OPARG; */
#define FUTEX_OP_OPARG_SHIFT 8 /* Use (1 << OPARG) instead of OPARG. */
#define FUTEX_OP_CMP_EQ 0 /* if (oldval == CMPARG) wake */
#define FUTEX_OP_CMP_NE 1 /* if (oldval != CMPARG) wake */
#define FUTEX_OP_CMP_LT 2 /* if (oldval < CMPARG) wake */
#define FUTEX_OP_CMP_LE 3 /* if (oldval <= CMPARG) wake */
#define FUTEX_OP_CMP_GT 4 /* if (oldval > CMPARG) wake */
#define FUTEX_OP_CMP_GE 5 /* if (oldval >= CMPARG) wake */
// @}
/* FUTEX_WAKE_OP will perform atomically
int oldval = *(int *)UADDR2;
*(int *)UADDR2 = oldval OP OPARG;
if (oldval CMP CMPARG)
wake UADDR2; */
#define FUTEX_OP(op, oparg, cmp, cmparg) \
(((op & 0xf) << 28) | ((cmp & 0xf) << 24) \
| ((oparg & 0xfff) << 12) | (cmparg & 0xfff))
/*
* bitset with all bits set for the FUTEX_xxx_BITSET OPs to request a
* match of any bit.
*/
#define FUTEX_BITSET_MATCH_ANY 0xffffffff
#ifdef __KERNEL__
#include <lwk/spinlock.h>
#include <lwk/list.h>
#include <lwk/waitq.h>
#include <arch/futex.h>
#define FUTEX_HASHBITS 8 /* 256 entries in each futex hash tbl */
/** Futex tracking structure.
*
* A futex has a woken state, just like tasks have TASK_RUNNING.
* It is considered woken when list_empty(&futex->link) || futex->lock_ptr == 0.
* The order of wakup is always to make the first condition true, then
* wake up futex->waitq, then make the second condition true.
*/
struct futex {
struct list_head link;
struct waitq waitq;
spinlock_t * lock_ptr;
uint32_t __user * uaddr;
uint32_t bitset;
};
struct futex_queue {
spinlock_t lock;
struct list_head futex_list;
};
extern void
futex_queue_init(
struct futex_queue * queue
);
extern int
futex(
uint32_t __user * uaddr,
int op,
uint32_t val,
uint64_t timeout,
uint32_t __user * uaddr2,
uint32_t val2,
uint32_t val3,
int fshared
);
extern long
sys_futex(
uint32_t __user * uaddr,
int op,
uint32_t val,
struct timespec __user * utime,
uint32_t __user * uaddr2,
uint32_t val3
);
#endif
#endif