#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 #include #include #include #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