blob: 4d9cbcfe8813cd2a9b6dbf2ed5ee754ce9378dbb [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>
Kenny Root420878c2011-02-16 11:55:58 -080029#include <machine/asm.h>
Andy McFaddenfcd00eb2010-05-28 13:31:45 -070030#include <machine/cpu-features.h>
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070031
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070032#define FUTEX_WAIT 0
33#define FUTEX_WAKE 1
34
Andy McFaddenfcd00eb2010-05-28 13:31:45 -070035#if defined(__ARM_HAVE_LDREX_STREX)
36/*
37 * ===========================================================================
38 * ARMv6+ implementation
39 * ===========================================================================
40 */
41
42/* r0(addr) -> r0(old) */
Kenny Root420878c2011-02-16 11:55:58 -080043ENTRY(__atomic_dec)
Andy McFaddenfcd00eb2010-05-28 13:31:45 -070044 mov r1, r0 @ copy addr so we don't clobber it
451: ldrex r0, [r1] @ load current value into r0
46 sub r2, r0, #1 @ generate new value into r2
47 strex r3, r2, [r1] @ try to store new value; result in r3
48 cmp r3, #0 @ success?
49 bxeq lr @ yes, return
50 b 1b @ no, retry
Kenny Root420878c2011-02-16 11:55:58 -080051END(__atomic_dec)
Andy McFaddenfcd00eb2010-05-28 13:31:45 -070052
53/* r0(addr) -> r0(old) */
Kenny Root420878c2011-02-16 11:55:58 -080054ENTRY(__atomic_inc)
Andy McFaddenfcd00eb2010-05-28 13:31:45 -070055 mov r1, r0
561: ldrex r0, [r1]
57 add r2, r0, #1
58 strex r3, r2, [r1]
59 cmp r3, #0
60 bxeq lr
61 b 1b
Kenny Root420878c2011-02-16 11:55:58 -080062END(__atomic_inc)
Andy McFaddenfcd00eb2010-05-28 13:31:45 -070063
64/* r0(old) r1(new) r2(addr) -> r0(zero_if_succeeded) */
Kenny Root420878c2011-02-16 11:55:58 -080065ENTRY(__atomic_cmpxchg)
Andy McFaddenfcd00eb2010-05-28 13:31:45 -0700661: mov ip, #2 @ ip=2 means "new != old"
67 ldrex r3, [r2] @ load current value into r3
68 teq r0, r3 @ new == old?
69 strexeq ip, r1, [r2] @ yes, try store, set ip to 0 or 1
70 teq ip, #1 @ strex failure?
71 beq 1b @ yes, retry
72 mov r0, ip @ return 0 on success, 2 on failure
73 bx lr
Kenny Root420878c2011-02-16 11:55:58 -080074END(__atomic_cmpxchg)
Andy McFaddenfcd00eb2010-05-28 13:31:45 -070075
76/* r0(new) r1(addr) -> r0(old) */
Kenny Root420878c2011-02-16 11:55:58 -080077ENTRY(__atomic_swap)
Andy McFaddenfcd00eb2010-05-28 13:31:45 -0700781: ldrex r2, [r1]
79 strex r3, r0, [r1]
80 teq r3, #0
81 bne 1b
82 mov r0, r2
83 bx lr
Kenny Root420878c2011-02-16 11:55:58 -080084END(__atomic_swap)
Andy McFaddenfcd00eb2010-05-28 13:31:45 -070085
86#else /*not defined __ARM_HAVE_LDREX_STREX*/
87/*
88 * ===========================================================================
89 * Pre-ARMv6 implementation
90 * ===========================================================================
91 */
92
93 /* int __kernel_cmpxchg(int oldval, int newval, int* ptr) */
94 .equ kernel_cmpxchg, 0xFFFF0FC0
95 .equ kernel_atomic_base, 0xFFFF0FFF
96
97/* r0(addr) -> r0(old) */
Kenny Root420878c2011-02-16 11:55:58 -080098ENTRY(__atomic_dec)
Ben Chengbd192b42009-09-15 13:41:14 -070099 .save {r4, lr}
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700100 stmdb sp!, {r4, lr}
101 mov r2, r0
1021: @ atomic_dec
103 ldr r0, [r2]
104 mov r3, #kernel_atomic_base
105 add lr, pc, #4
106 sub r1, r0, #1
107 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
108 bcc 1b
109 add r0, r1, #1
110 ldmia sp!, {r4, lr}
111 bx lr
Kenny Root420878c2011-02-16 11:55:58 -0800112END(__atomic_dec)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700113
Andy McFaddenfcd00eb2010-05-28 13:31:45 -0700114/* r0(addr) -> r0(old) */
Kenny Root420878c2011-02-16 11:55:58 -0800115ENTRY(__atomic_inc)
Ben Chengbd192b42009-09-15 13:41:14 -0700116 .save {r4, lr}
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700117 stmdb sp!, {r4, lr}
118 mov r2, r0
1191: @ atomic_inc
120 ldr r0, [r2]
121 mov r3, #kernel_atomic_base
122 add lr, pc, #4
123 add r1, r0, #1
124 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
125 bcc 1b
126 sub r0, r1, #1
127 ldmia sp!, {r4, lr}
128 bx lr
Kenny Root420878c2011-02-16 11:55:58 -0800129END(__atomic_inc)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700130
131/* r0(old) r1(new) r2(addr) -> r0(zero_if_succeeded) */
Kenny Root420878c2011-02-16 11:55:58 -0800132ENTRY(__atomic_cmpxchg)
Ben Chengbd192b42009-09-15 13:41:14 -0700133 .save {r4, lr}
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700134 stmdb sp!, {r4, lr}
135 mov r4, r0 /* r4 = save oldvalue */
1361: @ atomic_cmpxchg
137 mov r3, #kernel_atomic_base
138 add lr, pc, #4
139 mov r0, r4 /* r0 = oldvalue */
140 add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
141 bcs 2f /* swap was made. we're good, return. */
142 ldr r3, [r2] /* swap not made, see if it's because *ptr!=oldvalue */
143 cmp r3, r4
144 beq 1b
1452: @ atomic_cmpxchg
146 ldmia sp!, {r4, lr}
147 bx lr
Kenny Root420878c2011-02-16 11:55:58 -0800148END(__atomic_cmpxchg)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700149
150/* r0(new) r1(addr) -> r0(old) */
Kenny Root420878c2011-02-16 11:55:58 -0800151ENTRY(__atomic_swap)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700152 swp r0, r0, [r1]
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700153 bx lr
Kenny Root420878c2011-02-16 11:55:58 -0800154END(__atomic_swap)
Andy McFaddenfcd00eb2010-05-28 13:31:45 -0700155
156#endif /*not defined __ARM_HAVE_LDREX_STREX*/
157
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700158
159/* __futex_wait(*ftx, val, *timespec) */
David 'Digit' Turner88f06cd2010-03-18 17:13:41 -0700160/* __futex_wake(*ftx, counter) */
161/* __futex_syscall3(*ftx, op, val) */
162/* __futex_syscall4(*ftx, op, val, *timespec) */
163
164.global __futex_wait
165.type __futex_wait, %function
166
167.global __futex_wake
168.type __futex_wake, %function
169
170.global __futex_syscall3
171.type __futex_syscall3, %function
172
173.global __futex_syscall4
174.type __futex_syscall4, %function
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700175
176#if __ARM_EABI__
177
Kenny Root420878c2011-02-16 11:55:58 -0800178ENTRY(__futex_syscall3)
David 'Digit' Turner88f06cd2010-03-18 17:13:41 -0700179 stmdb sp!, {r4, r7}
180 .save {r4, r7}
181 ldr r7, =__NR_futex
182 swi #0
183 ldmia sp!, {r4, r7}
184 bx lr
Kenny Root420878c2011-02-16 11:55:58 -0800185END(__futex_syscall3)
David 'Digit' Turner88f06cd2010-03-18 17:13:41 -0700186
Kenny Root420878c2011-02-16 11:55:58 -0800187ENTRY(__futex_wait)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700188 stmdb sp!, {r4, r7}
189 .save {r4, r7}
190 mov r3, r2
191 mov r2, r1
192 mov r1, #FUTEX_WAIT
193 ldr r7, =__NR_futex
194 swi #0
195 ldmia sp!, {r4, r7}
196 bx lr
Kenny Root420878c2011-02-16 11:55:58 -0800197END(__futex_wait)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700198
Kenny Root420878c2011-02-16 11:55:58 -0800199ENTRY(__futex_wake)
Andy McFaddenfcd00eb2010-05-28 13:31:45 -0700200 .save {r4, r7}
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700201 stmdb sp!, {r4, r7}
202 mov r2, r1
203 mov r1, #FUTEX_WAKE
204 ldr r7, =__NR_futex
205 swi #0
206 ldmia sp!, {r4, r7}
207 bx lr
Kenny Root420878c2011-02-16 11:55:58 -0800208END(__futex_wake)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700209
210#else
211
Kenny Root420878c2011-02-16 11:55:58 -0800212ENTRY(__futex_syscall3)
David 'Digit' Turner88f06cd2010-03-18 17:13:41 -0700213 swi #__NR_futex
214 bx lr
Kenny Root420878c2011-02-16 11:55:58 -0800215END(__futex_syscall3)
David 'Digit' Turner88f06cd2010-03-18 17:13:41 -0700216
Kenny Root420878c2011-02-16 11:55:58 -0800217ENTRY(__futex_wait)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700218 mov r3, r2
219 mov r2, r1
220 mov r1, #FUTEX_WAIT
221 swi #__NR_futex
222 bx lr
Kenny Root420878c2011-02-16 11:55:58 -0800223END(__futex_wait)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700224
Kenny Root420878c2011-02-16 11:55:58 -0800225ENTRY(__futex_wake)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700226 mov r2, r1
227 mov r1, #FUTEX_WAKE
228 swi #__NR_futex
229 bx lr
Kenny Root420878c2011-02-16 11:55:58 -0800230END(__futex_wake)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700231
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700232#endif
David 'Digit' Turner88f06cd2010-03-18 17:13:41 -0700233
Kenny Root420878c2011-02-16 11:55:58 -0800234ENTRY(__futex_syscall4)
David 'Digit' Turner88f06cd2010-03-18 17:13:41 -0700235 b __futex_syscall3
Kenny Root420878c2011-02-16 11:55:58 -0800236END(__futex_syscall4)