blob: f8b23e63432db4d609cf707e1e3ae84999475f6a [file] [log] [blame]
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001/*
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 Project1dc9e472009-03-03 19:28:35 -080046 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 Project1dc9e472009-03-03 19:28:35 -080059
60__atomic_inc:
Ben Chengbd192b42009-09-15 13:41:14 -070061 .fnstart
62 .save {r4, lr}
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080063 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 Project1dc9e472009-03-03 19:28:35 -080076
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 Project1dc9e472009-03-03 19:28:35 -080081 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 Project1dc9e472009-03-03 19:28:35 -080096#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) */
141__atomic_swap:
142 swp r0, r0, [r1]
143 bx lr
144
145/* __futex_wait(*ftx, val, *timespec) */
146/* __futex_syscall(*ftx, op, val, *timespec, *addr2, val3) */
147
148#if __ARM_EABI__
149
150__futex_wait:
151 .fnstart
152 stmdb sp!, {r4, r7}
153 .save {r4, r7}
154 mov r3, r2
155 mov r2, r1
156 mov r1, #FUTEX_WAIT
157 ldr r7, =__NR_futex
158 swi #0
159 ldmia sp!, {r4, r7}
160 bx lr
161 .fnend
162
163__futex_wake:
164 stmdb sp!, {r4, r7}
165 mov r2, r1
166 mov r1, #FUTEX_WAKE
167 ldr r7, =__NR_futex
168 swi #0
169 ldmia sp!, {r4, r7}
170 bx lr
171
172#else
173
174__futex_wait:
175 mov r3, r2
176 mov r2, r1
177 mov r1, #FUTEX_WAIT
178 swi #__NR_futex
179 bx lr
180
181__futex_wake:
182 mov r2, r1
183 mov r1, #FUTEX_WAKE
184 swi #__NR_futex
185 bx lr
186
187#endif