1096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand/*
2096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand * Copyright (C) 2010 The Android Open Source Project
3096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand *
4096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand * Licensed under the Apache License, Version 2.0 (the "License");
5096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand * you may not use this file except in compliance with the License.
6096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand * You may obtain a copy of the License at
7096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand *
8096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand *      http://www.apache.org/licenses/LICENSE-2.0
9096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand *
10096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand * Unless required by applicable law or agreed to in writing, software
11096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand * distributed under the License is distributed on an "AS IS" BASIS,
12096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand * See the License for the specific language governing permissions and
14096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand * limitations under the License.
15096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand */
16096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
17096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand#ifndef ANDROID_CUTILS_ATOMIC_MIPS_H
18096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand#define ANDROID_CUTILS_ATOMIC_MIPS_H
19096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
20096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand#include <stdint.h>
21096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
225206d5971208fab8208669dabc98bbb9f7e4a45aBen Cheng#ifndef ANDROID_ATOMIC_INLINE
235206d5971208fab8208669dabc98bbb9f7e4a45aBen Cheng#define ANDROID_ATOMIC_INLINE inline __attribute__((always_inline))
245206d5971208fab8208669dabc98bbb9f7e4a45aBen Cheng#endif
255206d5971208fab8208669dabc98bbb9f7e4a45aBen Cheng
265206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE void android_compiler_barrier(void)
27096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
28096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    __asm__ __volatile__ ("" : : : "memory");
29096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
30096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
31096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand#if ANDROID_SMP == 0
325206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE void android_memory_barrier(void)
33096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
34096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_compiler_barrier();
35096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
365206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void)
37096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
38096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_compiler_barrier();
39096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
40096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand#else
415206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE void android_memory_barrier(void)
42096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
43096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    __asm__ __volatile__ ("sync" : : : "memory");
44096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
455206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE void android_memory_store_barrier(void)
46096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
47096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    __asm__ __volatile__ ("sync" : : : "memory");
48096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
49096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand#endif
50096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
515206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE int32_t
525206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengandroid_atomic_acquire_load(volatile const int32_t *ptr)
53096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
54096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    int32_t value = *ptr;
55096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_memory_barrier();
56096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return value;
57096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
58096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
595206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE int32_t
605206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengandroid_atomic_release_load(volatile const int32_t *ptr)
61096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
62096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_memory_barrier();
63096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return *ptr;
64096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
65096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
665206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE void
675206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengandroid_atomic_acquire_store(int32_t value, volatile int32_t *ptr)
68096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
69096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    *ptr = value;
70096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_memory_barrier();
71096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
72096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
735206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE void
745206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengandroid_atomic_release_store(int32_t value, volatile int32_t *ptr)
75096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
76096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_memory_barrier();
77096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    *ptr = value;
78096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
79096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
805206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE int
815206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengandroid_atomic_cas(int32_t old_value, int32_t new_value, volatile int32_t *ptr)
82096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
83096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    int32_t prev, status;
84096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    do {
85096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        __asm__ __volatile__ (
86096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "    ll     %[prev], (%[ptr])\n"
87096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "    li     %[status], 1\n"
88096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "    bne    %[prev], %[old], 9f\n"
89096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "    move   %[status], %[new_value]\n"
90096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "    sc     %[status], (%[ptr])\n"
91096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "9:\n"
92096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            : [prev] "=&r" (prev), [status] "=&r" (status)
93096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            : [ptr] "r" (ptr), [old] "r" (old_value), [new_value] "r" (new_value)
94096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            );
95096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    } while (__builtin_expect(status == 0, 0));
96096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return prev != old_value;
97096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
98096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
995206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE int
1005206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengandroid_atomic_acquire_cas(int32_t old_value,
1015206d5971208fab8208669dabc98bbb9f7e4a45aBen Cheng                           int32_t new_value,
1025206d5971208fab8208669dabc98bbb9f7e4a45aBen Cheng                           volatile int32_t *ptr)
103096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
104096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    int status = android_atomic_cas(old_value, new_value, ptr);
105096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_memory_barrier();
106096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return status;
107096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
108096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
1095206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE int
1105206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengandroid_atomic_release_cas(int32_t old_value,
1115206d5971208fab8208669dabc98bbb9f7e4a45aBen Cheng                           int32_t new_value,
1125206d5971208fab8208669dabc98bbb9f7e4a45aBen Cheng                           volatile int32_t *ptr)
113096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
114096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_memory_barrier();
115096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return android_atomic_cas(old_value, new_value, ptr);
116096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
117096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
118096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
1195206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE int32_t
1205206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengandroid_atomic_swap(int32_t new_value, volatile int32_t *ptr)
121096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
122096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    int32_t prev, status;
123096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    do {
124096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    __asm__ __volatile__ (
125096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    move %[status], %[new_value]\n"
126096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    ll %[prev], (%[ptr])\n"
127096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    sc %[status], (%[ptr])\n"
128096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        : [prev] "=&r" (prev), [status] "=&r" (status)
129096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        : [ptr] "r" (ptr), [new_value] "r" (new_value)
130096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        );
131096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    } while (__builtin_expect(status == 0, 0));
132096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_memory_barrier();
133096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return prev;
134096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
135096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
1365206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE int32_t
1375206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengandroid_atomic_add(int32_t increment, volatile int32_t *ptr)
138096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
139096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    int32_t prev, status;
140096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_memory_barrier();
141096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    do {
142096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        __asm__ __volatile__ (
143096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    ll    %[prev], (%[ptr])\n"
144096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    addu  %[status], %[prev], %[inc]\n"
145096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    sc    %[status], (%[ptr])\n"
146096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        :  [status] "=&r" (status), [prev] "=&r" (prev)
147096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        :  [ptr] "r" (ptr), [inc] "Ir" (increment)
148096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        );
149096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    } while (__builtin_expect(status == 0, 0));
150096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return prev;
151096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
152096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
1535206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE int32_t
1545206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengandroid_atomic_inc(volatile int32_t *addr)
155096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
156096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return android_atomic_add(1, addr);
157096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
158096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
1595206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE int32_t
1605206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengandroid_atomic_dec(volatile int32_t *addr)
161096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
162096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return android_atomic_add(-1, addr);
163096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
164096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
1655206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE int32_t
1665206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengandroid_atomic_and(int32_t value, volatile int32_t *ptr)
167096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
168096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    int32_t prev, status;
169096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_memory_barrier();
170096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    do {
171096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        __asm__ __volatile__ (
172096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    ll    %[prev], (%[ptr])\n"
173096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    and   %[status], %[prev], %[value]\n"
174096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    sc    %[status], (%[ptr])\n"
175096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        : [prev] "=&r" (prev), [status] "=&r" (status)
176096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        : [ptr] "r" (ptr), [value] "Ir" (value)
177096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            );
178096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    } while (__builtin_expect(status == 0, 0));
179096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return prev;
180096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
181096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
1825206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE int32_t
1835206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengandroid_atomic_or(int32_t value, volatile int32_t *ptr)
184096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
185096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    int32_t prev, status;
186096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_memory_barrier();
187096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    do {
188096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        __asm__ __volatile__ (
189096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    ll    %[prev], (%[ptr])\n"
190096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    or    %[status], %[prev], %[value]\n"
191096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    sc    %[status], (%[ptr])\n"
192096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        : [prev] "=&r" (prev), [status] "=&r" (status)
193096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        : [ptr] "r" (ptr), [value] "Ir" (value)
194096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            );
195096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    } while (__builtin_expect(status == 0, 0));
196096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return prev;
197096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
198096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
199096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand#endif /* ANDROID_CUTILS_ATOMIC_MIPS_H */
200