blob: 55c642f8dea56a65ace8a78d177505c9427b2c6b [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
46#if 1
47 .equ kernel_cmpxchg, 0xFFFF0FC0
48 .equ kernel_atomic_base, 0xFFFF0FFF
49__atomic_dec:
Ben Chengbd192b42009-09-15 13:41:14 -070050 .fnstart
51 .save {r4, lr}
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070052 stmdb sp!, {r4, lr}
53 mov r2, r0
541: @ atomic_dec
55 ldr r0, [r2]
56 mov r3, #kernel_atomic_base
57 add lr, pc, #4
58 sub r1, r0, #1
59 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
60 bcc 1b
61 add r0, r1, #1
62 ldmia sp!, {r4, lr}
63 bx lr
Ben Chengbd192b42009-09-15 13:41:14 -070064 .fnend
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070065
66__atomic_inc:
Ben Chengbd192b42009-09-15 13:41:14 -070067 .fnstart
68 .save {r4, lr}
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070069 stmdb sp!, {r4, lr}
70 mov r2, r0
711: @ atomic_inc
72 ldr r0, [r2]
73 mov r3, #kernel_atomic_base
74 add lr, pc, #4
75 add r1, r0, #1
76 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
77 bcc 1b
78 sub r0, r1, #1
79 ldmia sp!, {r4, lr}
80 bx lr
Ben Chengbd192b42009-09-15 13:41:14 -070081 .fnend
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070082
83/* r0(old) r1(new) r2(addr) -> r0(zero_if_succeeded) */
84__atomic_cmpxchg:
Ben Chengbd192b42009-09-15 13:41:14 -070085 .fnstart
86 .save {r4, lr}
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070087 stmdb sp!, {r4, lr}
88 mov r4, r0 /* r4 = save oldvalue */
891: @ atomic_cmpxchg
90 mov r3, #kernel_atomic_base
91 add lr, pc, #4
92 mov r0, r4 /* r0 = oldvalue */
93 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
94 bcs 2f /* swap was made. we're good, return. */
95 ldr r3, [r2] /* swap not made, see if it's because *ptr!=oldvalue */
96 cmp r3, r4
97 beq 1b
982: @ atomic_cmpxchg
99 ldmia sp!, {r4, lr}
100 bx lr
Ben Chengbd192b42009-09-15 13:41:14 -0700101 .fnend
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700102#else
103#define KUSER_CMPXCHG 0xffffffc0
104
105/* r0(old) r1(new) r2(addr) -> r0(zero_if_succeeded) */
106__atomic_cmpxchg:
107 stmdb sp!, {r4, lr}
108 mov r4, r0 /* r4 = save oldvalue */
1091: add lr, pc, #4
110 mov r0, r4 /* r0 = oldvalue */
111 mov pc, #KUSER_CMPXCHG
112 bcs 2f /* swap was made. we're good, return. */
113 ldr r3, [r2] /* swap not made, see if it's because *ptr!=oldvalue */
114 cmp r3, r4
115 beq 1b
1162: ldmia sp!, {r4, lr}
117 bx lr
118
119/* r0(addr) -> r0(old) */
120__atomic_dec:
121 stmdb sp!, {r4, lr}
122 mov r2, r0 /* address */
1231: ldr r0, [r2] /* oldvalue */
124 add lr, pc, #4
125 sub r1, r0, #1 /* newvalue = oldvalue - 1 */
126 mov pc, #KUSER_CMPXCHG
127 bcc 1b /* no swap, try again until we get it right */
128 mov r0, ip /* swapped, return the old value */
129 ldmia sp!, {r4, lr}
130 bx lr
131
132/* r0(addr) -> r0(old) */
133__atomic_inc:
134 stmdb sp!, {r4, lr}
135 mov r2, r0 /* address */
1361: ldr r0, [r2] /* oldvalue */
137 add lr, pc, #4
138 add 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#endif
145
146/* r0(new) r1(addr) -> r0(old) */
vinay harugop76ec6892009-09-09 20:53:39 +0530147/* replaced swp instruction with ldrex/strex for ARMv6 & ARMv7 */
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700148__atomic_swap:
vinay harugop76ec6892009-09-09 20:53:39 +0530149#if defined (_ARM_HAVE_LDREX_STREX)
1501: ldrex r2, [r1]
151 strex r3, r0, [r1]
152 teq r3, #0
153 bne 1b
154 mov r0, r2
155 mcr p15, 0, r0, c7, c10, 5 /* or, use dmb */
156#else
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700157 swp r0, r0, [r1]
vinay harugop76ec6892009-09-09 20:53:39 +0530158#endif
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700159 bx lr
160
161/* __futex_wait(*ftx, val, *timespec) */
162/* __futex_syscall(*ftx, op, val, *timespec, *addr2, val3) */
163
164#if __ARM_EABI__
165
166__futex_wait:
167 .fnstart
168 stmdb sp!, {r4, r7}
169 .save {r4, r7}
170 mov r3, r2
171 mov r2, r1
172 mov r1, #FUTEX_WAIT
173 ldr r7, =__NR_futex
174 swi #0
175 ldmia sp!, {r4, r7}
176 bx lr
177 .fnend
178
179__futex_wake:
180 stmdb sp!, {r4, r7}
181 mov r2, r1
182 mov r1, #FUTEX_WAKE
183 ldr r7, =__NR_futex
184 swi #0
185 ldmia sp!, {r4, r7}
186 bx lr
187
188#else
189
190__futex_wait:
191 mov r3, r2
192 mov r2, r1
193 mov r1, #FUTEX_WAIT
194 swi #__NR_futex
195 bx lr
196
197__futex_wake:
198 mov r2, r1
199 mov r1, #FUTEX_WAKE
200 swi #__NR_futex
201 bx lr
202
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700203#endif