root/arch/parisc/include/asm/futex.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. _futex_spin_lock_irqsave
  2. _futex_spin_unlock_irqrestore
  3. arch_futex_atomic_op_inuser
  4. futex_atomic_cmpxchg_inatomic

   1 /* SPDX-License-Identifier: GPL-2.0 */
   2 #ifndef _ASM_PARISC_FUTEX_H
   3 #define _ASM_PARISC_FUTEX_H
   4 
   5 #ifdef __KERNEL__
   6 
   7 #include <linux/futex.h>
   8 #include <linux/uaccess.h>
   9 #include <asm/atomic.h>
  10 #include <asm/errno.h>
  11 
  12 /* The following has to match the LWS code in syscall.S.  We have
  13    sixteen four-word locks. */
  14 
  15 static inline void
  16 _futex_spin_lock_irqsave(u32 __user *uaddr, unsigned long int *flags)
  17 {
  18         extern u32 lws_lock_start[];
  19         long index = ((long)uaddr & 0xf0) >> 2;
  20         arch_spinlock_t *s = (arch_spinlock_t *)&lws_lock_start[index];
  21         local_irq_save(*flags);
  22         arch_spin_lock(s);
  23 }
  24 
  25 static inline void
  26 _futex_spin_unlock_irqrestore(u32 __user *uaddr, unsigned long int *flags)
  27 {
  28         extern u32 lws_lock_start[];
  29         long index = ((long)uaddr & 0xf0) >> 2;
  30         arch_spinlock_t *s = (arch_spinlock_t *)&lws_lock_start[index];
  31         arch_spin_unlock(s);
  32         local_irq_restore(*flags);
  33 }
  34 
  35 static inline int
  36 arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
  37 {
  38         unsigned long int flags;
  39         int oldval, ret;
  40         u32 tmp;
  41 
  42         _futex_spin_lock_irqsave(uaddr, &flags);
  43         pagefault_disable();
  44 
  45         ret = -EFAULT;
  46         if (unlikely(get_user(oldval, uaddr) != 0))
  47                 goto out_pagefault_enable;
  48 
  49         ret = 0;
  50         tmp = oldval;
  51 
  52         switch (op) {
  53         case FUTEX_OP_SET:
  54                 tmp = oparg;
  55                 break;
  56         case FUTEX_OP_ADD:
  57                 tmp += oparg;
  58                 break;
  59         case FUTEX_OP_OR:
  60                 tmp |= oparg;
  61                 break;
  62         case FUTEX_OP_ANDN:
  63                 tmp &= ~oparg;
  64                 break;
  65         case FUTEX_OP_XOR:
  66                 tmp ^= oparg;
  67                 break;
  68         default:
  69                 ret = -ENOSYS;
  70         }
  71 
  72         if (ret == 0 && unlikely(put_user(tmp, uaddr) != 0))
  73                 ret = -EFAULT;
  74 
  75 out_pagefault_enable:
  76         pagefault_enable();
  77         _futex_spin_unlock_irqrestore(uaddr, &flags);
  78 
  79         if (!ret)
  80                 *oval = oldval;
  81 
  82         return ret;
  83 }
  84 
  85 static inline int
  86 futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
  87                               u32 oldval, u32 newval)
  88 {
  89         u32 val;
  90         unsigned long flags;
  91 
  92         /* futex.c wants to do a cmpxchg_inatomic on kernel NULL, which is
  93          * our gateway page, and causes no end of trouble...
  94          */
  95         if (uaccess_kernel() && !uaddr)
  96                 return -EFAULT;
  97 
  98         if (!access_ok(uaddr, sizeof(u32)))
  99                 return -EFAULT;
 100 
 101         /* HPPA has no cmpxchg in hardware and therefore the
 102          * best we can do here is use an array of locks. The
 103          * lock selected is based on a hash of the userspace
 104          * address. This should scale to a couple of CPUs.
 105          */
 106 
 107         _futex_spin_lock_irqsave(uaddr, &flags);
 108         if (unlikely(get_user(val, uaddr) != 0)) {
 109                 _futex_spin_unlock_irqrestore(uaddr, &flags);
 110                 return -EFAULT;
 111         }
 112 
 113         if (val == oldval && unlikely(put_user(newval, uaddr) != 0)) {
 114                 _futex_spin_unlock_irqrestore(uaddr, &flags);
 115                 return -EFAULT;
 116         }
 117 
 118         *uval = val;
 119         _futex_spin_unlock_irqrestore(uaddr, &flags);
 120 
 121         return 0;
 122 }
 123 
 124 #endif /*__KERNEL__*/
 125 #endif /*_ASM_PARISC_FUTEX_H*/

/* [<][>][^][v][top][bottom][index][help] */