blob: 0cd0b92dedbaac14832cc3fa7531891144eff87f [file] [log] [blame]
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -07001/*
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:
Ben Chengbd192b42009-09-15 13:41:14 -070044 .fnstart
45 .save {r4, lr}
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070046 stmdb sp!, {r4, lr}
47 mov r2, r0
481: @ atomic_dec
49 ldr r0, [r2]
50 mov r3, #kernel_atomic_base
51 add lr, pc, #4
52 sub r1, r0, #1
53 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
54 bcc 1b
55 add r0, r1, #1
56 ldmia sp!, {r4, lr}
57 bx lr
Ben Chengbd192b42009-09-15 13:41:14 -070058 .fnend
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070059
60__atomic_inc:
Ben Chengbd192b42009-09-15 13:41:14 -070061 .fnstart
62 .save {r4, lr}
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070063 stmdb sp!, {r4, lr}
64 mov r2, r0
651: @ atomic_inc
66 ldr r0, [r2]
67 mov r3, #kernel_atomic_base
68 add lr, pc, #4
69 add r1, r0, #1
70 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
71 bcc 1b
72 sub r0, r1, #1
73 ldmia sp!, {r4, lr}
74 bx lr
Ben Chengbd192b42009-09-15 13:41:14 -070075 .fnend
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070076
77/* r0(old) r1(new) r2(addr) -> r0(zero_if_succeeded) */
78__atomic_cmpxchg:
Ben Chengbd192b42009-09-15 13:41:14 -070079 .fnstart
80 .save {r4, lr}
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070081 stmdb sp!, {r4, lr}
82 mov r4, r0 /* r4 = save oldvalue */
831: @ atomic_cmpxchg
84 mov r3, #kernel_atomic_base
85 add lr, pc, #4
86 mov r0, r4 /* r0 = oldvalue */
87 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
88 bcs 2f /* swap was made. we're good, return. */
89 ldr r3, [r2] /* swap not made, see if it's because *ptr!=oldvalue */
90 cmp r3, r4
91 beq 1b
922: @ atomic_cmpxchg
93 ldmia sp!, {r4, lr}
94 bx lr
Ben Chengbd192b42009-09-15 13:41:14 -070095 .fnend
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070096#else
97#define KUSER_CMPXCHG 0xffffffc0
98
99/* r0(old) r1(new) r2(addr) -> r0(zero_if_succeeded) */
100__atomic_cmpxchg:
101 stmdb sp!, {r4, lr}
102 mov r4, r0 /* r4 = save oldvalue */
1031: add lr, pc, #4
104 mov r0, r4 /* r0 = oldvalue */
105 mov pc, #KUSER_CMPXCHG
106 bcs 2f /* swap was made. we're good, return. */
107 ldr r3, [r2] /* swap not made, see if it's because *ptr!=oldvalue */
108 cmp r3, r4
109 beq 1b
1102: ldmia sp!, {r4, lr}
111 bx lr
112
113/* r0(addr) -> r0(old) */
114__atomic_dec:
115 stmdb sp!, {r4, lr}
116 mov r2, r0 /* address */
1171: ldr r0, [r2] /* oldvalue */
118 add lr, pc, #4
119 sub r1, r0, #1 /* newvalue = oldvalue - 1 */
120 mov pc, #KUSER_CMPXCHG
121 bcc 1b /* no swap, try again until we get it right */
122 mov r0, ip /* swapped, return the old value */
123 ldmia sp!, {r4, lr}
124 bx lr
125
126/* r0(addr) -> r0(old) */
127__atomic_inc:
128 stmdb sp!, {r4, lr}
129 mov r2, r0 /* address */
1301: ldr r0, [r2] /* oldvalue */
131 add lr, pc, #4
132 add r1, r0, #1 /* newvalue = oldvalue + 1 */
133 mov pc, #KUSER_CMPXCHG
134 bcc 1b /* no swap, try again until we get it right */
135 mov r0, ip /* swapped, return the old value */
136 ldmia sp!, {r4, lr}
137 bx lr
138#endif
139
140/* r0(new) r1(addr) -> r0(old) */
vinay harugop76ec6892009-09-09 20:53:39 +0530141/* replaced swp instruction with ldrex/strex for ARMv6 & ARMv7 */
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700142__atomic_swap:
vinay harugop76ec6892009-09-09 20:53:39 +0530143#if defined (_ARM_HAVE_LDREX_STREX)
1441: ldrex r2, [r1]
145 strex r3, r0, [r1]
146 teq r3, #0
147 bne 1b
148 mov r0, r2
149 mcr p15, 0, r0, c7, c10, 5 /* or, use dmb */
150#else
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700151 swp r0, r0, [r1]
vinay harugop76ec6892009-09-09 20:53:39 +0530152#endif
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700153 bx lr
154
155/* __futex_wait(*ftx, val, *timespec) */
156/* __futex_syscall(*ftx, op, val, *timespec, *addr2, val3) */
157
158#if __ARM_EABI__
159
160__futex_wait:
161 .fnstart
162 stmdb sp!, {r4, r7}
163 .save {r4, r7}
164 mov r3, r2
165 mov r2, r1
166 mov r1, #FUTEX_WAIT
167 ldr r7, =__NR_futex
168 swi #0
169 ldmia sp!, {r4, r7}
170 bx lr
171 .fnend
172
173__futex_wake:
174 stmdb sp!, {r4, r7}
175 mov r2, r1
176 mov r1, #FUTEX_WAKE
177 ldr r7, =__NR_futex
178 swi #0
179 ldmia sp!, {r4, r7}
180 bx lr
181
182#else
183
184__futex_wait:
185 mov r3, r2
186 mov r2, r1
187 mov r1, #FUTEX_WAIT
188 swi #__NR_futex
189 bx lr
190
191__futex_wake:
192 mov r2, r1
193 mov r1, #FUTEX_WAKE
194 swi #__NR_futex
195 bx lr
196
197#endif