blob: d94f6b14de8a27a4df284c913b346f279855a588 [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>
Andy McFaddenfcd00eb2010-05-28 13:31:45 -070029#include <machine/cpu-features.h>
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070030
31.global __atomic_cmpxchg
Doug Kwand548a262009-12-03 16:26:04 -080032.type __atomic_cmpxchg, %function
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070033.global __atomic_swap
Doug Kwand548a262009-12-03 16:26:04 -080034.type __atomic_swap, %function
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070035.global __atomic_dec
Doug Kwand548a262009-12-03 16:26:04 -080036.type __atomic_dec, %function
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070037.global __atomic_inc
Doug Kwand548a262009-12-03 16:26:04 -080038.type __atomic_inc, %function
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070039
40#define FUTEX_WAIT 0
41#define FUTEX_WAKE 1
42
Andy McFaddenfcd00eb2010-05-28 13:31:45 -070043#if defined(__ARM_HAVE_LDREX_STREX)
44/*
45 * ===========================================================================
46 * ARMv6+ implementation
47 * ===========================================================================
48 */
49
50/* r0(addr) -> r0(old) */
51__atomic_dec:
52 .fnstart
53 mov r1, r0 @ copy addr so we don't clobber it
541: ldrex r0, [r1] @ load current value into r0
55 sub r2, r0, #1 @ generate new value into r2
56 strex r3, r2, [r1] @ try to store new value; result in r3
57 cmp r3, #0 @ success?
58 bxeq lr @ yes, return
59 b 1b @ no, retry
60 .fnend
61
62/* r0(addr) -> r0(old) */
63__atomic_inc:
64 .fnstart
65 mov r1, r0
661: ldrex r0, [r1]
67 add r2, r0, #1
68 strex r3, r2, [r1]
69 cmp r3, #0
70 bxeq lr
71 b 1b
72 .fnend
73
74/* r0(old) r1(new) r2(addr) -> r0(zero_if_succeeded) */
75__atomic_cmpxchg:
76 .fnstart
771: mov ip, #2 @ ip=2 means "new != old"
78 ldrex r3, [r2] @ load current value into r3
79 teq r0, r3 @ new == old?
80 strexeq ip, r1, [r2] @ yes, try store, set ip to 0 or 1
81 teq ip, #1 @ strex failure?
82 beq 1b @ yes, retry
83 mov r0, ip @ return 0 on success, 2 on failure
84 bx lr
85 .fnend
86
87/* r0(new) r1(addr) -> r0(old) */
88__atomic_swap:
89 .fnstart
901: ldrex r2, [r1]
91 strex r3, r0, [r1]
92 teq r3, #0
93 bne 1b
94 mov r0, r2
95 bx lr
96 .fnend
97
98#else /*not defined __ARM_HAVE_LDREX_STREX*/
99/*
100 * ===========================================================================
101 * Pre-ARMv6 implementation
102 * ===========================================================================
103 */
104
105 /* int __kernel_cmpxchg(int oldval, int newval, int* ptr) */
106 .equ kernel_cmpxchg, 0xFFFF0FC0
107 .equ kernel_atomic_base, 0xFFFF0FFF
108
109/* r0(addr) -> r0(old) */
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700110__atomic_dec:
Ben Chengbd192b42009-09-15 13:41:14 -0700111 .fnstart
112 .save {r4, lr}
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700113 stmdb sp!, {r4, lr}
114 mov r2, r0
1151: @ atomic_dec
116 ldr r0, [r2]
117 mov r3, #kernel_atomic_base
118 add lr, pc, #4
119 sub r1, r0, #1
120 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
121 bcc 1b
122 add r0, r1, #1
123 ldmia sp!, {r4, lr}
124 bx lr
Ben Chengbd192b42009-09-15 13:41:14 -0700125 .fnend
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700126
Andy McFaddenfcd00eb2010-05-28 13:31:45 -0700127/* r0(addr) -> r0(old) */
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700128__atomic_inc:
Ben Chengbd192b42009-09-15 13:41:14 -0700129 .fnstart
130 .save {r4, lr}
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700131 stmdb sp!, {r4, lr}
132 mov r2, r0
1331: @ atomic_inc
134 ldr r0, [r2]
135 mov r3, #kernel_atomic_base
136 add lr, pc, #4
137 add r1, r0, #1
138 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
139 bcc 1b
140 sub r0, r1, #1
141 ldmia sp!, {r4, lr}
142 bx lr
Ben Chengbd192b42009-09-15 13:41:14 -0700143 .fnend
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700144
145/* r0(old) r1(new) r2(addr) -> r0(zero_if_succeeded) */
146__atomic_cmpxchg:
Ben Chengbd192b42009-09-15 13:41:14 -0700147 .fnstart
148 .save {r4, lr}
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700149 stmdb sp!, {r4, lr}
150 mov r4, r0 /* r4 = save oldvalue */
1511: @ atomic_cmpxchg
152 mov r3, #kernel_atomic_base
153 add lr, pc, #4
154 mov r0, r4 /* r0 = oldvalue */
155 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
156 bcs 2f /* swap was made. we're good, return. */
157 ldr r3, [r2] /* swap not made, see if it's because *ptr!=oldvalue */
158 cmp r3, r4
159 beq 1b
1602: @ atomic_cmpxchg
161 ldmia sp!, {r4, lr}
162 bx lr
Ben Chengbd192b42009-09-15 13:41:14 -0700163 .fnend
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700164
165/* r0(new) r1(addr) -> r0(old) */
166__atomic_swap:
Andy McFaddenfcd00eb2010-05-28 13:31:45 -0700167 .fnstart
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700168 swp r0, r0, [r1]
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700169 bx lr
Andy McFaddenfcd00eb2010-05-28 13:31:45 -0700170 .fnend
171
172#endif /*not defined __ARM_HAVE_LDREX_STREX*/
173
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700174
175/* __futex_wait(*ftx, val, *timespec) */
David 'Digit' Turner88f06cd2010-03-18 17:13:41 -0700176/* __futex_wake(*ftx, counter) */
177/* __futex_syscall3(*ftx, op, val) */
178/* __futex_syscall4(*ftx, op, val, *timespec) */
179
180.global __futex_wait
181.type __futex_wait, %function
182
183.global __futex_wake
184.type __futex_wake, %function
185
186.global __futex_syscall3
187.type __futex_syscall3, %function
188
189.global __futex_syscall4
190.type __futex_syscall4, %function
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700191
192#if __ARM_EABI__
193
David 'Digit' Turner88f06cd2010-03-18 17:13:41 -0700194__futex_syscall3:
195 .fnstart
196 stmdb sp!, {r4, r7}
197 .save {r4, r7}
198 ldr r7, =__NR_futex
199 swi #0
200 ldmia sp!, {r4, r7}
201 bx lr
202 .fnend
203
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700204__futex_wait:
205 .fnstart
206 stmdb sp!, {r4, r7}
207 .save {r4, r7}
208 mov r3, r2
209 mov r2, r1
210 mov r1, #FUTEX_WAIT
211 ldr r7, =__NR_futex
212 swi #0
213 ldmia sp!, {r4, r7}
214 bx lr
215 .fnend
216
217__futex_wake:
Andy McFaddenfcd00eb2010-05-28 13:31:45 -0700218 .fnstart
219 .save {r4, r7}
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700220 stmdb sp!, {r4, r7}
221 mov r2, r1
222 mov r1, #FUTEX_WAKE
223 ldr r7, =__NR_futex
224 swi #0
225 ldmia sp!, {r4, r7}
226 bx lr
Andy McFaddenfcd00eb2010-05-28 13:31:45 -0700227 .fnend
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700228
229#else
230
David 'Digit' Turner88f06cd2010-03-18 17:13:41 -0700231__futex_syscall3:
232 swi #__NR_futex
233 bx lr
234
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700235__futex_wait:
236 mov r3, r2
237 mov r2, r1
238 mov r1, #FUTEX_WAIT
239 swi #__NR_futex
240 bx lr
241
242__futex_wake:
243 mov r2, r1
244 mov r1, #FUTEX_WAKE
245 swi #__NR_futex
246 bx lr
247
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700248#endif
David 'Digit' Turner88f06cd2010-03-18 17:13:41 -0700249
250__futex_syscall4:
251 b __futex_syscall3