/* The following has to match the LWS code in syscall.S. We have * 256 four-word locks. We use bits 20-27 of the futex virtual * address for the hash index.
*/
staticinlineint
arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
{ extern u32 lws_lock_start[]; unsignedlong ua = (unsignedlong)uaddr;
arch_spinlock_t *s; unsignedlong flags; int oldval, ret;
u32 tmp;
s = (arch_spinlock_t *)&lws_lock_start[_futex_hash_index(ua)];
_futex_spin_lock_irqsave(s, &flags);
/* Return -EFAULT if we encounter a page fault or COW break */ if (unlikely(get_user(oldval, uaddr) != 0)) {
ret = -EFAULT; goto out_pagefault_enable;
}
ret = 0;
tmp = oldval;
switch (op) { case FUTEX_OP_SET:
tmp = oparg; break; case FUTEX_OP_ADD:
tmp += oparg; break; case FUTEX_OP_OR:
tmp |= oparg; break; case FUTEX_OP_ANDN:
tmp &= ~oparg; break; case FUTEX_OP_XOR:
tmp ^= oparg; break; default:
ret = -ENOSYS; goto out_pagefault_enable;
}
if (unlikely(put_user(tmp, uaddr) != 0))
ret = -EFAULT;
if (!access_ok(uaddr, sizeof(u32))) return -EFAULT;
/* HPPA has no cmpxchg in hardware and therefore the * best we can do here is use an array of locks. The * lock selected is based on a hash of the virtual * address of the futex. This should scale to a couple * of CPUs.
*/
s = (arch_spinlock_t *)&lws_lock_start[_futex_hash_index(ua)];
_futex_spin_lock_irqsave(s, &flags); if (unlikely(get_user(val, uaddr) != 0)) {
_futex_spin_unlock_irqrestore(s, &flags); return -EFAULT;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.