1 #ifndef _ASM_PARISC_FUTEX_H
2 #define _ASM_PARISC_FUTEX_H
6 #include <linux/futex.h>
7 #include <linux/uaccess.h>
8 #include <asm/atomic.h>
11 /* The following has to match the LWS code in syscall.S. We have
12 sixteen four-word locks. */
15 _futex_spin_lock_irqsave(u32 __user *uaddr, unsigned long int *flags)
17 extern u32 lws_lock_start[];
18 long index = ((long)uaddr & 0xf0) >> 2;
19 arch_spinlock_t *s = (arch_spinlock_t *)&lws_lock_start[index];
20 local_irq_save(*flags);
25 _futex_spin_unlock_irqrestore(u32 __user *uaddr, unsigned long int *flags)
27 extern u32 lws_lock_start[];
28 long index = ((long)uaddr & 0xf0) >> 2;
29 arch_spinlock_t *s = (arch_spinlock_t *)&lws_lock_start[index];
31 local_irq_restore(*flags);
35 arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
37 unsigned long int flags;
43 _futex_spin_lock_irqsave(uaddr, &flags);
47 /* *(int *)UADDR2 = OPARG; */
48 ret = get_user(oldval, uaddr);
50 ret = put_user(oparg, uaddr);
53 /* *(int *)UADDR2 += OPARG; */
54 ret = get_user(oldval, uaddr);
57 ret = put_user(val, uaddr);
61 /* *(int *)UADDR2 |= OPARG; */
62 ret = get_user(oldval, uaddr);
65 ret = put_user(val, uaddr);
69 /* *(int *)UADDR2 &= ~OPARG; */
70 ret = get_user(oldval, uaddr);
72 val = oldval & ~oparg;
73 ret = put_user(val, uaddr);
77 /* *(int *)UADDR2 ^= OPARG; */
78 ret = get_user(oldval, uaddr);
81 ret = put_user(val, uaddr);
88 _futex_spin_unlock_irqrestore(uaddr, &flags);
98 /* Non-atomic version */
100 futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
101 u32 oldval, u32 newval)
107 /* futex.c wants to do a cmpxchg_inatomic on kernel NULL, which is
108 * our gateway page, and causes no end of trouble...
110 if (segment_eq(KERNEL_DS, get_fs()) && !uaddr)
113 if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
116 /* HPPA has no cmpxchg in hardware and therefore the
117 * best we can do here is use an array of locks. The
118 * lock selected is based on a hash of the userspace
119 * address. This should scale to a couple of CPUs.
122 _futex_spin_lock_irqsave(uaddr, &flags);
124 ret = get_user(val, uaddr);
126 if (!ret && val == oldval)
127 ret = put_user(newval, uaddr);
131 _futex_spin_unlock_irqrestore(uaddr, &flags);
136 #endif /*__KERNEL__*/
137 #endif /*_ASM_PARISC_FUTEX_H*/