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}
36096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand#else
375206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE void android_memory_barrier(void)
38096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
39096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    __asm__ __volatile__ ("sync" : : : "memory");
40096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
41096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand#endif
42096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
435206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE int32_t
445206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengandroid_atomic_acquire_load(volatile const int32_t *ptr)
45096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
46096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    int32_t value = *ptr;
47096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_memory_barrier();
48096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return value;
49096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
50096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
515206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE int32_t
525206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengandroid_atomic_release_load(volatile const int32_t *ptr)
53096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
54096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_memory_barrier();
55096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return *ptr;
56096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
57096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
585206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE void
595206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengandroid_atomic_acquire_store(int32_t value, volatile int32_t *ptr)
60096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
61096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    *ptr = value;
62096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_memory_barrier();
63096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
64096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
655206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE void
665206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengandroid_atomic_release_store(int32_t value, volatile int32_t *ptr)
67096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
68096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_memory_barrier();
69096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    *ptr = value;
70096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
71096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
725206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE int
735206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengandroid_atomic_cas(int32_t old_value, int32_t new_value, volatile int32_t *ptr)
74096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
75096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    int32_t prev, status;
76096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    do {
77096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        __asm__ __volatile__ (
78096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "    ll     %[prev], (%[ptr])\n"
79096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "    li     %[status], 1\n"
80096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "    bne    %[prev], %[old], 9f\n"
81096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "    move   %[status], %[new_value]\n"
82096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "    sc     %[status], (%[ptr])\n"
83096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "9:\n"
84096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            : [prev] "=&r" (prev), [status] "=&r" (status)
85096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            : [ptr] "r" (ptr), [old] "r" (old_value), [new_value] "r" (new_value)
86096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            );
87096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    } while (__builtin_expect(status == 0, 0));
88096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return prev != old_value;
89096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
90096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
915206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE int
925206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengandroid_atomic_acquire_cas(int32_t old_value,
935206d5971208fab8208669dabc98bbb9f7e4a45aBen Cheng                           int32_t new_value,
945206d5971208fab8208669dabc98bbb9f7e4a45aBen Cheng                           volatile int32_t *ptr)
95096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
96096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    int status = android_atomic_cas(old_value, new_value, ptr);
97096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_memory_barrier();
98096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return status;
99096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
100096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
1015206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE int
1025206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengandroid_atomic_release_cas(int32_t old_value,
1035206d5971208fab8208669dabc98bbb9f7e4a45aBen Cheng                           int32_t new_value,
1045206d5971208fab8208669dabc98bbb9f7e4a45aBen Cheng                           volatile int32_t *ptr)
105096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
106096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_memory_barrier();
107096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return android_atomic_cas(old_value, new_value, ptr);
108096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
109096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
110096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
1115206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE int32_t
1125206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengandroid_atomic_add(int32_t increment, volatile int32_t *ptr)
113096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
114096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    int32_t prev, status;
115096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_memory_barrier();
116096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    do {
117096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        __asm__ __volatile__ (
118096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    ll    %[prev], (%[ptr])\n"
119096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    addu  %[status], %[prev], %[inc]\n"
120096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    sc    %[status], (%[ptr])\n"
121096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        :  [status] "=&r" (status), [prev] "=&r" (prev)
122096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        :  [ptr] "r" (ptr), [inc] "Ir" (increment)
123096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        );
124096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    } while (__builtin_expect(status == 0, 0));
125096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return prev;
126096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
127096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
1285206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE int32_t
1295206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengandroid_atomic_inc(volatile int32_t *addr)
130096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
131096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return android_atomic_add(1, addr);
132096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
133096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
1345206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE int32_t
1355206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengandroid_atomic_dec(volatile int32_t *addr)
136096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
137096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return android_atomic_add(-1, addr);
138096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
139096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
1405206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE int32_t
1415206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengandroid_atomic_and(int32_t value, volatile int32_t *ptr)
142096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
143096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    int32_t prev, status;
144096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_memory_barrier();
145096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    do {
146096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        __asm__ __volatile__ (
147096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    ll    %[prev], (%[ptr])\n"
148096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    and   %[status], %[prev], %[value]\n"
149096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    sc    %[status], (%[ptr])\n"
150096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        : [prev] "=&r" (prev), [status] "=&r" (status)
151096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        : [ptr] "r" (ptr), [value] "Ir" (value)
152096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            );
153096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    } while (__builtin_expect(status == 0, 0));
154096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return prev;
155096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
156096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
1575206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengextern ANDROID_ATOMIC_INLINE int32_t
1585206d5971208fab8208669dabc98bbb9f7e4a45aBen Chengandroid_atomic_or(int32_t value, volatile int32_t *ptr)
159096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
160096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    int32_t prev, status;
161096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_memory_barrier();
162096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    do {
163096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        __asm__ __volatile__ (
164096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    ll    %[prev], (%[ptr])\n"
165096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    or    %[status], %[prev], %[value]\n"
166096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    sc    %[status], (%[ptr])\n"
167096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        : [prev] "=&r" (prev), [status] "=&r" (status)
168096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        : [ptr] "r" (ptr), [value] "Ir" (value)
169096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            );
170096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    } while (__builtin_expect(status == 0, 0));
171096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return prev;
172096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
173096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
174096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand#endif /* ANDROID_CUTILS_ATOMIC_MIPS_H */
175