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
22096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sandextern inline void android_compiler_barrier(void)
23096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
24096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    __asm__ __volatile__ ("" : : : "memory");
25096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
26096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
27096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand#if ANDROID_SMP == 0
28096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sandextern inline void android_memory_barrier(void)
29096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
30096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_compiler_barrier();
31096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
32096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sandextern inline void android_memory_store_barrier(void)
33096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
34096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_compiler_barrier();
35096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
36096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand#else
37096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sandextern inline void android_memory_barrier(void)
38096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
39096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    __asm__ __volatile__ ("sync" : : : "memory");
40096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
41096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sandextern inline void android_memory_store_barrier(void)
42096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
43096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    __asm__ __volatile__ ("sync" : : : "memory");
44096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
45096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand#endif
46096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
47096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sandextern inline int32_t android_atomic_acquire_load(volatile const int32_t *ptr)
48096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
49096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    int32_t value = *ptr;
50096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_memory_barrier();
51096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return value;
52096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
53096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
54096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sandextern inline int32_t android_atomic_release_load(volatile const int32_t *ptr)
55096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
56096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_memory_barrier();
57096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return *ptr;
58096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
59096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
60096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sandextern inline void android_atomic_acquire_store(int32_t value,
61096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                                                volatile int32_t *ptr)
62096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
63096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    *ptr = value;
64096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_memory_barrier();
65096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
66096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
67096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sandextern inline void android_atomic_release_store(int32_t value,
68096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                                                volatile int32_t *ptr)
69096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
70096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_memory_barrier();
71096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    *ptr = value;
72096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
73096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
74096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sandextern inline int android_atomic_cas(int32_t old_value, int32_t new_value,
75096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                                     volatile int32_t *ptr)
76096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
77096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    int32_t prev, status;
78096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    do {
79096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        __asm__ __volatile__ (
80096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "    ll     %[prev], (%[ptr])\n"
81096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "    li     %[status], 1\n"
82096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "    bne    %[prev], %[old], 9f\n"
83096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "    move   %[status], %[new_value]\n"
84096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "    sc     %[status], (%[ptr])\n"
85096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            "9:\n"
86096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            : [prev] "=&r" (prev), [status] "=&r" (status)
87096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            : [ptr] "r" (ptr), [old] "r" (old_value), [new_value] "r" (new_value)
88096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            );
89096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    } while (__builtin_expect(status == 0, 0));
90096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return prev != old_value;
91096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
92096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
93096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sandextern inline int android_atomic_acquire_cas(int32_t old_value,
94096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                                             int32_t new_value,
95096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                                             volatile int32_t *ptr)
96096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
97096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    int status = android_atomic_cas(old_value, new_value, ptr);
98096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_memory_barrier();
99096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return status;
100096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
101096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
102096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sandextern inline int android_atomic_release_cas(int32_t old_value,
103096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                                             int32_t new_value,
104096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                                             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
111096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sandextern inline int32_t android_atomic_swap(int32_t new_value,
112096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                                          volatile int32_t *ptr)
113096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
114096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    int32_t prev, status;
115096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    do {
116096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    __asm__ __volatile__ (
117096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    move %[status], %[new_value]\n"
118096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    ll %[prev], (%[ptr])\n"
119096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    sc %[status], (%[ptr])\n"
120096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        : [prev] "=&r" (prev), [status] "=&r" (status)
121096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        : [ptr] "r" (ptr), [new_value] "r" (new_value)
122096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        );
123096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    } while (__builtin_expect(status == 0, 0));
124096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_memory_barrier();
125096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return prev;
126096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
127096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
128096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sandextern inline int32_t android_atomic_add(int32_t increment,
129096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand                                         volatile int32_t *ptr)
130096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
131096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    int32_t prev, status;
132096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_memory_barrier();
133096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    do {
134096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        __asm__ __volatile__ (
135096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    ll    %[prev], (%[ptr])\n"
136096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    addu  %[status], %[prev], %[inc]\n"
137096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    sc    %[status], (%[ptr])\n"
138096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        :  [status] "=&r" (status), [prev] "=&r" (prev)
139096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        :  [ptr] "r" (ptr), [inc] "Ir" (increment)
140096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        );
141096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    } while (__builtin_expect(status == 0, 0));
142096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return prev;
143096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
144096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
145096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sandextern inline int32_t android_atomic_inc(volatile int32_t *addr)
146096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
147096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return android_atomic_add(1, addr);
148096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
149096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
150096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sandextern inline int32_t android_atomic_dec(volatile int32_t *addr)
151096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
152096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return android_atomic_add(-1, addr);
153096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
154096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
155096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sandextern inline int32_t android_atomic_and(int32_t value, volatile int32_t *ptr)
156096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
157096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    int32_t prev, status;
158096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_memory_barrier();
159096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    do {
160096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        __asm__ __volatile__ (
161096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    ll    %[prev], (%[ptr])\n"
162096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    and   %[status], %[prev], %[value]\n"
163096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    sc    %[status], (%[ptr])\n"
164096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        : [prev] "=&r" (prev), [status] "=&r" (status)
165096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        : [ptr] "r" (ptr), [value] "Ir" (value)
166096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            );
167096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    } while (__builtin_expect(status == 0, 0));
168096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return prev;
169096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
170096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
171096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sandextern inline int32_t android_atomic_or(int32_t value, volatile int32_t *ptr)
172096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand{
173096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    int32_t prev, status;
174096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    android_memory_barrier();
175096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    do {
176096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        __asm__ __volatile__ (
177096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    ll    %[prev], (%[ptr])\n"
178096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    or    %[status], %[prev], %[value]\n"
179096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        "    sc    %[status], (%[ptr])\n"
180096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        : [prev] "=&r" (prev), [status] "=&r" (status)
181096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand        : [ptr] "r" (ptr), [value] "Ir" (value)
182096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand            );
183096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    } while (__builtin_expect(status == 0, 0));
184096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand    return prev;
185096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand}
186096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand
187096041174b1d8cc09b06c51053b2b7e8545bd93fDuane Sand#endif /* ANDROID_CUTILS_ATOMIC_MIPS_H */
188