blob: b2da09f072490fe9f78bfa119592667543f6bda7 [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:
44 stmdb sp!, {r4, lr}
45 mov r2, r0
461: @ atomic_dec
47 ldr r0, [r2]
48 mov r3, #kernel_atomic_base
49 add lr, pc, #4
50 sub r1, r0, #1
51 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
52 bcc 1b
53 add r0, r1, #1
54 ldmia sp!, {r4, lr}
55 bx lr
56
57__atomic_inc:
58 stmdb sp!, {r4, lr}
59 mov r2, r0
601: @ atomic_inc
61 ldr r0, [r2]
62 mov r3, #kernel_atomic_base
63 add lr, pc, #4
64 add r1, r0, #1
65 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
66 bcc 1b
67 sub r0, r1, #1
68 ldmia sp!, {r4, lr}
69 bx lr
70
71/* r0(old) r1(new) r2(addr) -> r0(zero_if_succeeded) */
72__atomic_cmpxchg:
73 stmdb sp!, {r4, lr}
74 mov r4, r0 /* r4 = save oldvalue */
751: @ atomic_cmpxchg
76 mov r3, #kernel_atomic_base
77 add lr, pc, #4
78 mov r0, r4 /* r0 = oldvalue */
79 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
80 bcs 2f /* swap was made. we're good, return. */
81 ldr r3, [r2] /* swap not made, see if it's because *ptr!=oldvalue */
82 cmp r3, r4
83 beq 1b
842: @ atomic_cmpxchg
85 ldmia sp!, {r4, lr}
86 bx lr
87#else
88#define KUSER_CMPXCHG 0xffffffc0
89
90/* r0(old) r1(new) r2(addr) -> r0(zero_if_succeeded) */
91__atomic_cmpxchg:
92 stmdb sp!, {r4, lr}
93 mov r4, r0 /* r4 = save oldvalue */
941: add lr, pc, #4
95 mov r0, r4 /* r0 = oldvalue */
96 mov pc, #KUSER_CMPXCHG
97 bcs 2f /* swap was made. we're good, return. */
98 ldr r3, [r2] /* swap not made, see if it's because *ptr!=oldvalue */
99 cmp r3, r4
100 beq 1b
1012: ldmia sp!, {r4, lr}
102 bx lr
103
104/* r0(addr) -> r0(old) */
105__atomic_dec:
106 stmdb sp!, {r4, lr}
107 mov r2, r0 /* address */
1081: ldr r0, [r2] /* oldvalue */
109 add lr, pc, #4
110 sub r1, r0, #1 /* newvalue = oldvalue - 1 */
111 mov pc, #KUSER_CMPXCHG
112 bcc 1b /* no swap, try again until we get it right */
113 mov r0, ip /* swapped, return the old value */
114 ldmia sp!, {r4, lr}
115 bx lr
116
117/* r0(addr) -> r0(old) */
118__atomic_inc:
119 stmdb sp!, {r4, lr}
120 mov r2, r0 /* address */
1211: ldr r0, [r2] /* oldvalue */
122 add lr, pc, #4
123 add r1, r0, #1 /* newvalue = oldvalue + 1 */
124 mov pc, #KUSER_CMPXCHG
125 bcc 1b /* no swap, try again until we get it right */
126 mov r0, ip /* swapped, return the old value */
127 ldmia sp!, {r4, lr}
128 bx lr
129#endif
130
131/* r0(new) r1(addr) -> r0(old) */
132__atomic_swap:
133 swp r0, r0, [r1]
134 bx lr
135
136/* __futex_wait(*ftx, val, *timespec) */
137/* __futex_syscall(*ftx, op, val, *timespec, *addr2, val3) */
138
139#if __ARM_EABI__
140
141__futex_wait:
142 .fnstart
143 stmdb sp!, {r4, r7}
144 .save {r4, r7}
145 mov r3, r2
146 mov r2, r1
147 mov r1, #FUTEX_WAIT
148 ldr r7, =__NR_futex
149 swi #0
150 ldmia sp!, {r4, r7}
151 bx lr
152 .fnend
153
154__futex_wake:
155 stmdb sp!, {r4, r7}
156 mov r2, r1
157 mov r1, #FUTEX_WAKE
158 ldr r7, =__NR_futex
159 swi #0
160 ldmia sp!, {r4, r7}
161 bx lr
162
163#else
164
165__futex_wait:
166 mov r3, r2
167 mov r2, r1
168 mov r1, #FUTEX_WAIT
169 swi #__NR_futex
170 bx lr
171
172__futex_wake:
173 mov r2, r1
174 mov r1, #FUTEX_WAKE
175 swi #__NR_futex
176 bx lr
177
178#endif