linux/arch/arm/include/asm/locks.h
<<
>>
Prefs
   1/*
   2 *  arch/arm/include/asm/locks.h
   3 *
   4 *  Copyright (C) 2000 Russell King
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 *
  10 *  Interrupt safe locking assembler. 
  11 */
  12#ifndef __ASM_PROC_LOCKS_H
  13#define __ASM_PROC_LOCKS_H
  14
  15#if __LINUX_ARM_ARCH__ >= 6
  16
  17#define __down_op(ptr,fail)                     \
  18        ({                                      \
  19        __asm__ __volatile__(                   \
  20        "@ down_op\n"                           \
  21"1:     ldrex   lr, [%0]\n"                     \
  22"       sub     lr, lr, %1\n"                   \
  23"       strex   ip, lr, [%0]\n"                 \
  24"       teq     ip, #0\n"                       \
  25"       bne     1b\n"                           \
  26"       teq     lr, #0\n"                       \
  27"       movmi   ip, %0\n"                       \
  28"       blmi    " #fail                         \
  29        :                                       \
  30        : "r" (ptr), "I" (1)                    \
  31        : "ip", "lr", "cc");                    \
  32        smp_mb();                               \
  33        })
  34
  35#define __down_op_ret(ptr,fail)                 \
  36        ({                                      \
  37                unsigned int ret;               \
  38        __asm__ __volatile__(                   \
  39        "@ down_op_ret\n"                       \
  40"1:     ldrex   lr, [%1]\n"                     \
  41"       sub     lr, lr, %2\n"                   \
  42"       strex   ip, lr, [%1]\n"                 \
  43"       teq     ip, #0\n"                       \
  44"       bne     1b\n"                           \
  45"       teq     lr, #0\n"                       \
  46"       movmi   ip, %1\n"                       \
  47"       movpl   ip, #0\n"                       \
  48"       blmi    " #fail "\n"                    \
  49"       mov     %0, ip"                         \
  50        : "=&r" (ret)                           \
  51        : "r" (ptr), "I" (1)                    \
  52        : "ip", "lr", "cc");                    \
  53        smp_mb();                               \
  54        ret;                                    \
  55        })
  56
  57#define __up_op(ptr,wake)                       \
  58        ({                                      \
  59        smp_mb();                               \
  60        __asm__ __volatile__(                   \
  61        "@ up_op\n"                             \
  62"1:     ldrex   lr, [%0]\n"                     \
  63"       add     lr, lr, %1\n"                   \
  64"       strex   ip, lr, [%0]\n"                 \
  65"       teq     ip, #0\n"                       \
  66"       bne     1b\n"                           \
  67"       cmp     lr, #0\n"                       \
  68"       movle   ip, %0\n"                       \
  69"       blle    " #wake                         \
  70        :                                       \
  71        : "r" (ptr), "I" (1)                    \
  72        : "ip", "lr", "cc");                    \
  73        })
  74
  75/*
  76 * The value 0x01000000 supports up to 128 processors and
  77 * lots of processes.  BIAS must be chosen such that sub'ing
  78 * BIAS once per CPU will result in the long remaining
  79 * negative.
  80 */
  81#define RW_LOCK_BIAS      0x01000000
  82#define RW_LOCK_BIAS_STR "0x01000000"
  83
  84#define __down_op_write(ptr,fail)               \
  85        ({                                      \
  86        __asm__ __volatile__(                   \
  87        "@ down_op_write\n"                     \
  88"1:     ldrex   lr, [%0]\n"                     \
  89"       sub     lr, lr, %1\n"                   \
  90"       strex   ip, lr, [%0]\n"                 \
  91"       teq     ip, #0\n"                       \
  92"       bne     1b\n"                           \
  93"       teq     lr, #0\n"                       \
  94"       movne   ip, %0\n"                       \
  95"       blne    " #fail                         \
  96        :                                       \
  97        : "r" (ptr), "I" (RW_LOCK_BIAS)         \
  98        : "ip", "lr", "cc");                    \
  99        smp_mb();                               \
 100        })
 101
 102#define __up_op_write(ptr,wake)                 \
 103        ({                                      \
 104        smp_mb();                               \
 105        __asm__ __volatile__(                   \
 106        "@ up_op_write\n"                       \
 107"1:     ldrex   lr, [%0]\n"                     \
 108"       adds    lr, lr, %1\n"                   \
 109"       strex   ip, lr, [%0]\n"                 \
 110"       teq     ip, #0\n"                       \
 111"       bne     1b\n"                           \
 112"       movcs   ip, %0\n"                       \
 113"       blcs    " #wake                         \
 114        :                                       \
 115        : "r" (ptr), "I" (RW_LOCK_BIAS)         \
 116        : "ip", "lr", "cc");                    \
 117        })
 118
 119#define __down_op_read(ptr,fail)                \
 120        __down_op(ptr, fail)
 121
 122#define __up_op_read(ptr,wake)                  \
 123        ({                                      \
 124        smp_mb();                               \
 125        __asm__ __volatile__(                   \
 126        "@ up_op_read\n"                        \
 127"1:     ldrex   lr, [%0]\n"                     \
 128"       add     lr, lr, %1\n"                   \
 129"       strex   ip, lr, [%0]\n"                 \
 130"       teq     ip, #0\n"                       \
 131"       bne     1b\n"                           \
 132"       teq     lr, #0\n"                       \
 133"       moveq   ip, %0\n"                       \
 134"       bleq    " #wake                         \
 135        :                                       \
 136        : "r" (ptr), "I" (1)                    \
 137        : "ip", "lr", "cc");                    \
 138        })
 139
 140#else
 141
 142#define __down_op(ptr,fail)                     \
 143        ({                                      \
 144        __asm__ __volatile__(                   \
 145        "@ down_op\n"                           \
 146"       mrs     ip, cpsr\n"                     \
 147"       orr     lr, ip, #128\n"                 \
 148"       msr     cpsr_c, lr\n"                   \
 149"       ldr     lr, [%0]\n"                     \
 150"       subs    lr, lr, %1\n"                   \
 151"       str     lr, [%0]\n"                     \
 152"       msr     cpsr_c, ip\n"                   \
 153"       movmi   ip, %0\n"                       \
 154"       blmi    " #fail                         \
 155        :                                       \
 156        : "r" (ptr), "I" (1)                    \
 157        : "ip", "lr", "cc");                    \
 158        smp_mb();                               \
 159        })
 160
 161#define __down_op_ret(ptr,fail)                 \
 162        ({                                      \
 163                unsigned int ret;               \
 164        __asm__ __volatile__(                   \
 165        "@ down_op_ret\n"                       \
 166"       mrs     ip, cpsr\n"                     \
 167"       orr     lr, ip, #128\n"                 \
 168"       msr     cpsr_c, lr\n"                   \
 169"       ldr     lr, [%1]\n"                     \
 170"       subs    lr, lr, %2\n"                   \
 171"       str     lr, [%1]\n"                     \
 172"       msr     cpsr_c, ip\n"                   \
 173"       movmi   ip, %1\n"                       \
 174"       movpl   ip, #0\n"                       \
 175"       blmi    " #fail "\n"                    \
 176"       mov     %0, ip"                         \
 177        : "=&r" (ret)                           \
 178        : "r" (ptr), "I" (1)                    \
 179        : "ip", "lr", "cc");                    \
 180        smp_mb();                               \
 181        ret;                                    \
 182        })
 183
 184#define __up_op(ptr,wake)                       \
 185        ({                                      \
 186        smp_mb();                               \
 187        __asm__ __volatile__(                   \
 188        "@ up_op\n"                             \
 189"       mrs     ip, cpsr\n"                     \
 190"       orr     lr, ip, #128\n"                 \
 191"       msr     cpsr_c, lr\n"                   \
 192"       ldr     lr, [%0]\n"                     \
 193"       adds    lr, lr, %1\n"                   \
 194"       str     lr, [%0]\n"                     \
 195"       msr     cpsr_c, ip\n"                   \
 196"       movle   ip, %0\n"                       \
 197"       blle    " #wake                         \
 198        :                                       \
 199        : "r" (ptr), "I" (1)                    \
 200        : "ip", "lr", "cc");                    \
 201        })
 202
 203/*
 204 * The value 0x01000000 supports up to 128 processors and
 205 * lots of processes.  BIAS must be chosen such that sub'ing
 206 * BIAS once per CPU will result in the long remaining
 207 * negative.
 208 */
 209#define RW_LOCK_BIAS      0x01000000
 210#define RW_LOCK_BIAS_STR "0x01000000"
 211
 212#define __down_op_write(ptr,fail)               \
 213        ({                                      \
 214        __asm__ __volatile__(                   \
 215        "@ down_op_write\n"                     \
 216"       mrs     ip, cpsr\n"                     \
 217"       orr     lr, ip, #128\n"                 \
 218"       msr     cpsr_c, lr\n"                   \
 219"       ldr     lr, [%0]\n"                     \
 220"       subs    lr, lr, %1\n"                   \
 221"       str     lr, [%0]\n"                     \
 222"       msr     cpsr_c, ip\n"                   \
 223"       movne   ip, %0\n"                       \
 224"       blne    " #fail                         \
 225        :                                       \
 226        : "r" (ptr), "I" (RW_LOCK_BIAS)         \
 227        : "ip", "lr", "cc");                    \
 228        smp_mb();                               \
 229        })
 230
 231#define __up_op_write(ptr,wake)                 \
 232        ({                                      \
 233        __asm__ __volatile__(                   \
 234        "@ up_op_write\n"                       \
 235"       mrs     ip, cpsr\n"                     \
 236"       orr     lr, ip, #128\n"                 \
 237"       msr     cpsr_c, lr\n"                   \
 238"       ldr     lr, [%0]\n"                     \
 239"       adds    lr, lr, %1\n"                   \
 240"       str     lr, [%0]\n"                     \
 241"       msr     cpsr_c, ip\n"                   \
 242"       movcs   ip, %0\n"                       \
 243"       blcs    " #wake                         \
 244        :                                       \
 245        : "r" (ptr), "I" (RW_LOCK_BIAS)         \
 246        : "ip", "lr", "cc");                    \
 247        smp_mb();                               \
 248        })
 249
 250#define __down_op_read(ptr,fail)                \
 251        __down_op(ptr, fail)
 252
 253#define __up_op_read(ptr,wake)                  \
 254        ({                                      \
 255        smp_mb();                               \
 256        __asm__ __volatile__(                   \
 257        "@ up_op_read\n"                        \
 258"       mrs     ip, cpsr\n"                     \
 259"       orr     lr, ip, #128\n"                 \
 260"       msr     cpsr_c, lr\n"                   \
 261"       ldr     lr, [%0]\n"                     \
 262"       adds    lr, lr, %1\n"                   \
 263"       str     lr, [%0]\n"                     \
 264"       msr     cpsr_c, ip\n"                   \
 265"       moveq   ip, %0\n"                       \
 266"       bleq    " #wake                         \
 267        :                                       \
 268        : "r" (ptr), "I" (1)                    \
 269        : "ip", "lr", "cc");                    \
 270        })
 271
 272#endif
 273
 274#endif
 275