1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28#include <sys/linux-syscalls.h> 29 30.global __atomic_cmpxchg 31.global __atomic_swap 32.global __atomic_dec 33.global __atomic_inc 34.global __futex_wait 35.global __futex_wake 36 37#define FUTEX_WAIT 0 38#define FUTEX_WAKE 1 39 40#if 1 41 .equ kernel_cmpxchg, 0xFFFF0FC0 42 .equ kernel_atomic_base, 0xFFFF0FFF 43__atomic_dec: 44 stmdb sp!, {r4, lr} 45 mov r2, r0 461: @ atomic_dec 47 ldr r0, [r2] 48 mov r3, #kernel_atomic_base 49 add lr, pc, #4 50 sub r1, r0, #1 51 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base) 52 bcc 1b 53 add r0, r1, #1 54 ldmia sp!, {r4, lr} 55 bx lr 56 57__atomic_inc: 58 stmdb sp!, {r4, lr} 59 mov r2, r0 601: @ atomic_inc 61 ldr r0, [r2] 62 mov r3, #kernel_atomic_base 63 add lr, pc, #4 64 add r1, r0, #1 65 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base) 66 bcc 1b 67 sub r0, r1, #1 68 ldmia sp!, {r4, lr} 69 bx lr 70 71/* r0(old) r1(new) r2(addr) -> r0(zero_if_succeeded) */ 72__atomic_cmpxchg: 73 stmdb sp!, {r4, lr} 74 mov r4, r0 /* r4 = save oldvalue */ 751: @ atomic_cmpxchg 76 mov r3, #kernel_atomic_base 77 add lr, pc, #4 78 mov r0, r4 /* r0 = oldvalue */ 79 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base) 80 bcs 2f /* swap was made. we're good, return. */ 81 ldr r3, [r2] /* swap not made, see if it's because *ptr!=oldvalue */ 82 cmp r3, r4 83 beq 1b 842: @ atomic_cmpxchg 85 ldmia sp!, {r4, lr} 86 bx lr 87#else 88#define KUSER_CMPXCHG 0xffffffc0 89 90/* r0(old) r1(new) r2(addr) -> r0(zero_if_succeeded) */ 91__atomic_cmpxchg: 92 stmdb sp!, {r4, lr} 93 mov r4, r0 /* r4 = save oldvalue */ 941: add lr, pc, #4 95 mov r0, r4 /* r0 = oldvalue */ 96 mov pc, #KUSER_CMPXCHG 97 bcs 2f /* swap was made. we're good, return. */ 98 ldr r3, [r2] /* swap not made, see if it's because *ptr!=oldvalue */ 99 cmp r3, r4 100 beq 1b 1012: ldmia sp!, {r4, lr} 102 bx lr 103 104/* r0(addr) -> r0(old) */ 105__atomic_dec: 106 stmdb sp!, {r4, lr} 107 mov r2, r0 /* address */ 1081: ldr r0, [r2] /* oldvalue */ 109 add lr, pc, #4 110 sub r1, r0, #1 /* newvalue = oldvalue - 1 */ 111 mov pc, #KUSER_CMPXCHG 112 bcc 1b /* no swap, try again until we get it right */ 113 mov r0, ip /* swapped, return the old value */ 114 ldmia sp!, {r4, lr} 115 bx lr 116 117/* r0(addr) -> r0(old) */ 118__atomic_inc: 119 stmdb sp!, {r4, lr} 120 mov r2, r0 /* address */ 1211: ldr r0, [r2] /* oldvalue */ 122 add lr, pc, #4 123 add r1, r0, #1 /* newvalue = oldvalue + 1 */ 124 mov pc, #KUSER_CMPXCHG 125 bcc 1b /* no swap, try again until we get it right */ 126 mov r0, ip /* swapped, return the old value */ 127 ldmia sp!, {r4, lr} 128 bx lr 129#endif 130 131/* r0(new) r1(addr) -> r0(old) */ 132__atomic_swap: 133 swp r0, r0, [r1] 134 bx lr 135 136/* __futex_wait(*ftx, val, *timespec) */ 137/* __futex_syscall(*ftx, op, val, *timespec, *addr2, val3) */ 138 139#if __ARM_EABI__ 140 141__futex_wait: 142 .fnstart 143 stmdb sp!, {r4, r7} 144 .save {r4, r7} 145 mov r3, r2 146 mov r2, r1 147 mov r1, #FUTEX_WAIT 148 ldr r7, =__NR_futex 149 swi #0 150 ldmia sp!, {r4, r7} 151 bx lr 152 .fnend 153 154__futex_wake: 155 stmdb sp!, {r4, r7} 156 mov r2, r1 157 mov r1, #FUTEX_WAKE 158 ldr r7, =__NR_futex 159 swi #0 160 ldmia sp!, {r4, r7} 161 bx lr 162 163#else 164 165__futex_wait: 166 mov r3, r2 167 mov r2, r1 168 mov r1, #FUTEX_WAIT 169 swi #__NR_futex 170 bx lr 171 172__futex_wake: 173 mov r2, r1 174 mov r1, #FUTEX_WAKE 175 swi #__NR_futex 176 bx lr 177 178#endif 179