• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
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
179