blob: 5076fe360c74ee88937a6737e9499660b34cffb1 [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
Doug Kwand548a262009-12-03 16:26:04 -080031.type __atomic_cmpxchg, %function
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070032.global __atomic_swap
Doug Kwand548a262009-12-03 16:26:04 -080033.type __atomic_swap, %function
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070034.global __atomic_dec
Doug Kwand548a262009-12-03 16:26:04 -080035.type __atomic_dec, %function
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070036.global __atomic_inc
Doug Kwand548a262009-12-03 16:26:04 -080037.type __atomic_inc, %function
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070038.global __futex_wait
Doug Kwand548a262009-12-03 16:26:04 -080039.type __futex_wait, %function
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070040.global __futex_wake
Doug Kwand548a262009-12-03 16:26:04 -080041.type __futex_wake, %function
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070042
43#define FUTEX_WAIT 0
44#define FUTEX_WAKE 1
45
David 'Digit' Turnerba9c6f02010-03-10 16:44:08 -080046/* Private futexes belong to a single address space and cannot be
47 * shared among processes. They are however significantly faster to
48 * operate than standard futexes.
49 */
50.global __futex_wait_private
51.type __futex_wait_private, %function
52.global __futex_wake_private
53.type __futex_wake_private, %function
54
55#define FUTEX_PRIVATE_FLAG 128
56#define FUTEX_WAIT_PRIVATE (FUTEX_WAIT|FUTEX_PRIVATE_FLAG)
57#define FUTEX_WAKE_PRIVATE (FUTEX_WAKE|FUTEX_PRIVATE_FLAG)
58
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070059#if 1
60 .equ kernel_cmpxchg, 0xFFFF0FC0
61 .equ kernel_atomic_base, 0xFFFF0FFF
62__atomic_dec:
Ben Chengbd192b42009-09-15 13:41:14 -070063 .fnstart
64 .save {r4, lr}
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070065 stmdb sp!, {r4, lr}
66 mov r2, r0
671: @ atomic_dec
68 ldr r0, [r2]
69 mov r3, #kernel_atomic_base
70 add lr, pc, #4
71 sub r1, r0, #1
72 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
73 bcc 1b
74 add r0, r1, #1
75 ldmia sp!, {r4, lr}
76 bx lr
Ben Chengbd192b42009-09-15 13:41:14 -070077 .fnend
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070078
79__atomic_inc:
Ben Chengbd192b42009-09-15 13:41:14 -070080 .fnstart
81 .save {r4, lr}
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070082 stmdb sp!, {r4, lr}
83 mov r2, r0
841: @ atomic_inc
85 ldr r0, [r2]
86 mov r3, #kernel_atomic_base
87 add lr, pc, #4
88 add r1, r0, #1
89 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
90 bcc 1b
91 sub r0, r1, #1
92 ldmia sp!, {r4, lr}
93 bx lr
Ben Chengbd192b42009-09-15 13:41:14 -070094 .fnend
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070095
96/* r0(old) r1(new) r2(addr) -> r0(zero_if_succeeded) */
97__atomic_cmpxchg:
Ben Chengbd192b42009-09-15 13:41:14 -070098 .fnstart
99 .save {r4, lr}
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700100 stmdb sp!, {r4, lr}
101 mov r4, r0 /* r4 = save oldvalue */
1021: @ atomic_cmpxchg
103 mov r3, #kernel_atomic_base
104 add lr, pc, #4
105 mov r0, r4 /* r0 = oldvalue */
106 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
107 bcs 2f /* swap was made. we're good, return. */
108 ldr r3, [r2] /* swap not made, see if it's because *ptr!=oldvalue */
109 cmp r3, r4
110 beq 1b
1112: @ atomic_cmpxchg
112 ldmia sp!, {r4, lr}
113 bx lr
Ben Chengbd192b42009-09-15 13:41:14 -0700114 .fnend
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700115#else
116#define KUSER_CMPXCHG 0xffffffc0
117
118/* r0(old) r1(new) r2(addr) -> r0(zero_if_succeeded) */
119__atomic_cmpxchg:
120 stmdb sp!, {r4, lr}
121 mov r4, r0 /* r4 = save oldvalue */
1221: add lr, pc, #4
123 mov r0, r4 /* r0 = oldvalue */
124 mov pc, #KUSER_CMPXCHG
125 bcs 2f /* swap was made. we're good, return. */
126 ldr r3, [r2] /* swap not made, see if it's because *ptr!=oldvalue */
127 cmp r3, r4
128 beq 1b
1292: ldmia sp!, {r4, lr}
130 bx lr
131
132/* r0(addr) -> r0(old) */
133__atomic_dec:
134 stmdb sp!, {r4, lr}
135 mov r2, r0 /* address */
1361: ldr r0, [r2] /* oldvalue */
137 add lr, pc, #4
138 sub r1, r0, #1 /* newvalue = oldvalue - 1 */
139 mov pc, #KUSER_CMPXCHG
140 bcc 1b /* no swap, try again until we get it right */
141 mov r0, ip /* swapped, return the old value */
142 ldmia sp!, {r4, lr}
143 bx lr
144
145/* r0(addr) -> r0(old) */
146__atomic_inc:
147 stmdb sp!, {r4, lr}
148 mov r2, r0 /* address */
1491: ldr r0, [r2] /* oldvalue */
150 add lr, pc, #4
151 add r1, r0, #1 /* newvalue = oldvalue + 1 */
152 mov pc, #KUSER_CMPXCHG
153 bcc 1b /* no swap, try again until we get it right */
154 mov r0, ip /* swapped, return the old value */
155 ldmia sp!, {r4, lr}
156 bx lr
157#endif
158
159/* r0(new) r1(addr) -> r0(old) */
vinay harugop76ec6892009-09-09 20:53:39 +0530160/* replaced swp instruction with ldrex/strex for ARMv6 & ARMv7 */
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700161__atomic_swap:
vinay harugop76ec6892009-09-09 20:53:39 +0530162#if defined (_ARM_HAVE_LDREX_STREX)
1631: ldrex r2, [r1]
164 strex r3, r0, [r1]
165 teq r3, #0
166 bne 1b
167 mov r0, r2
168 mcr p15, 0, r0, c7, c10, 5 /* or, use dmb */
169#else
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700170 swp r0, r0, [r1]
vinay harugop76ec6892009-09-09 20:53:39 +0530171#endif
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700172 bx lr
173
174/* __futex_wait(*ftx, val, *timespec) */
175/* __futex_syscall(*ftx, op, val, *timespec, *addr2, val3) */
176
177#if __ARM_EABI__
178
179__futex_wait:
180 .fnstart
181 stmdb sp!, {r4, r7}
182 .save {r4, r7}
183 mov r3, r2
184 mov r2, r1
185 mov r1, #FUTEX_WAIT
186 ldr r7, =__NR_futex
187 swi #0
188 ldmia sp!, {r4, r7}
189 bx lr
190 .fnend
191
192__futex_wake:
193 stmdb sp!, {r4, r7}
194 mov r2, r1
195 mov r1, #FUTEX_WAKE
196 ldr r7, =__NR_futex
197 swi #0
198 ldmia sp!, {r4, r7}
199 bx lr
200
David 'Digit' Turnerba9c6f02010-03-10 16:44:08 -0800201__futex_wait_private:
202 .fnstart
203 stmdb sp!, {r4, r7}
204 .save {r4, r7}
205 mov r3, r2
206 mov r2, r1
207 mov r1, #FUTEX_WAIT_PRIVATE
208 ldr r7, =__NR_futex
209 swi #0
210 ldmia sp!, {r4, r7}
211 bx lr
212 .fnend
213
214__futex_wake_private:
215 stmdb sp!, {r4, r7}
216 mov r2, r1
217 mov r1, #FUTEX_WAKE_PRIVATE
218 ldr r7, =__NR_futex
219 swi #0
220 ldmia sp!, {r4, r7}
221 bx lr
222
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700223#else
224
225__futex_wait:
226 mov r3, r2
227 mov r2, r1
228 mov r1, #FUTEX_WAIT
229 swi #__NR_futex
230 bx lr
231
232__futex_wake:
233 mov r2, r1
234 mov r1, #FUTEX_WAKE
235 swi #__NR_futex
236 bx lr
237
David 'Digit' Turnerba9c6f02010-03-10 16:44:08 -0800238__futex_wait_private:
239 mov r3, r2
240 mov r2, r1
241 mov r1, #FUTEX_WAIT_PRIVATE
242 swi #__NR_futex
243 bx lr
244
245__futex_wake_private:
246 mov r2, r1
247 mov r1, #FUTEX_WAKE_PRIVATE
248 swi #__NR_futex
249 bx lr
250
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700251#endif