184c3e9923108122045d689f1d2412359ad5208ebDuane Sand/*
284c3e9923108122045d689f1d2412359ad5208ebDuane Sand * Copyright (C) 2010 The Android Open Source Project
384c3e9923108122045d689f1d2412359ad5208ebDuane Sand *
484c3e9923108122045d689f1d2412359ad5208ebDuane Sand * Licensed under the Apache License, Version 2.0 (the "License");
584c3e9923108122045d689f1d2412359ad5208ebDuane Sand * you may not use this file except in compliance with the License.
684c3e9923108122045d689f1d2412359ad5208ebDuane Sand * You may obtain a copy of the License at
784c3e9923108122045d689f1d2412359ad5208ebDuane Sand *
884c3e9923108122045d689f1d2412359ad5208ebDuane Sand *      http://www.apache.org/licenses/LICENSE-2.0
984c3e9923108122045d689f1d2412359ad5208ebDuane Sand *
1084c3e9923108122045d689f1d2412359ad5208ebDuane Sand * Unless required by applicable law or agreed to in writing, software
1184c3e9923108122045d689f1d2412359ad5208ebDuane Sand * distributed under the License is distributed on an "AS IS" BASIS,
1284c3e9923108122045d689f1d2412359ad5208ebDuane Sand * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1384c3e9923108122045d689f1d2412359ad5208ebDuane Sand * See the License for the specific language governing permissions and
1484c3e9923108122045d689f1d2412359ad5208ebDuane Sand * limitations under the License.
1584c3e9923108122045d689f1d2412359ad5208ebDuane Sand */
1684c3e9923108122045d689f1d2412359ad5208ebDuane Sand
1784c3e9923108122045d689f1d2412359ad5208ebDuane Sand#ifndef ANDROID_CUTILS_ATOMIC_MIPS64_H
1884c3e9923108122045d689f1d2412359ad5208ebDuane Sand#define ANDROID_CUTILS_ATOMIC_MIPS64_H
1984c3e9923108122045d689f1d2412359ad5208ebDuane Sand
2084c3e9923108122045d689f1d2412359ad5208ebDuane Sand#include <stdint.h>
2184c3e9923108122045d689f1d2412359ad5208ebDuane Sand
2284c3e9923108122045d689f1d2412359ad5208ebDuane Sand#ifndef ANDROID_ATOMIC_INLINE
2384c3e9923108122045d689f1d2412359ad5208ebDuane Sand#define ANDROID_ATOMIC_INLINE inline __attribute__((always_inline))
2484c3e9923108122045d689f1d2412359ad5208ebDuane Sand#endif
2584c3e9923108122045d689f1d2412359ad5208ebDuane Sand
2684c3e9923108122045d689f1d2412359ad5208ebDuane Sandextern ANDROID_ATOMIC_INLINE void android_compiler_barrier(void)
2784c3e9923108122045d689f1d2412359ad5208ebDuane Sand{
2884c3e9923108122045d689f1d2412359ad5208ebDuane Sand    __asm__ __volatile__ ("" : : : "memory");
2984c3e9923108122045d689f1d2412359ad5208ebDuane Sand}
3084c3e9923108122045d689f1d2412359ad5208ebDuane Sand
3184c3e9923108122045d689f1d2412359ad5208ebDuane Sandextern ANDROID_ATOMIC_INLINE void android_memory_barrier(void)
3284c3e9923108122045d689f1d2412359ad5208ebDuane Sand{
3384c3e9923108122045d689f1d2412359ad5208ebDuane Sand    __asm__ __volatile__ ("sync" : : : "memory");
3484c3e9923108122045d689f1d2412359ad5208ebDuane Sand}
3584c3e9923108122045d689f1d2412359ad5208ebDuane Sand
3684c3e9923108122045d689f1d2412359ad5208ebDuane Sandextern ANDROID_ATOMIC_INLINE
3784c3e9923108122045d689f1d2412359ad5208ebDuane Sandint32_t android_atomic_acquire_load(volatile const int32_t *ptr)
3884c3e9923108122045d689f1d2412359ad5208ebDuane Sand{
3984c3e9923108122045d689f1d2412359ad5208ebDuane Sand    int32_t value = *ptr;
4084c3e9923108122045d689f1d2412359ad5208ebDuane Sand    android_memory_barrier();
4184c3e9923108122045d689f1d2412359ad5208ebDuane Sand    return value;
4284c3e9923108122045d689f1d2412359ad5208ebDuane Sand}
4384c3e9923108122045d689f1d2412359ad5208ebDuane Sand
4484c3e9923108122045d689f1d2412359ad5208ebDuane Sandextern ANDROID_ATOMIC_INLINE
4584c3e9923108122045d689f1d2412359ad5208ebDuane Sandint32_t android_atomic_release_load(volatile const int32_t *ptr)
4684c3e9923108122045d689f1d2412359ad5208ebDuane Sand{
4784c3e9923108122045d689f1d2412359ad5208ebDuane Sand    android_memory_barrier();
4884c3e9923108122045d689f1d2412359ad5208ebDuane Sand    return *ptr;
4984c3e9923108122045d689f1d2412359ad5208ebDuane Sand}
5084c3e9923108122045d689f1d2412359ad5208ebDuane Sand
5184c3e9923108122045d689f1d2412359ad5208ebDuane Sandextern ANDROID_ATOMIC_INLINE
5284c3e9923108122045d689f1d2412359ad5208ebDuane Sandvoid android_atomic_acquire_store(int32_t value, volatile int32_t *ptr)
5384c3e9923108122045d689f1d2412359ad5208ebDuane Sand{
5484c3e9923108122045d689f1d2412359ad5208ebDuane Sand    *ptr = value;
5584c3e9923108122045d689f1d2412359ad5208ebDuane Sand    android_memory_barrier();
5684c3e9923108122045d689f1d2412359ad5208ebDuane Sand}
5784c3e9923108122045d689f1d2412359ad5208ebDuane Sand
5884c3e9923108122045d689f1d2412359ad5208ebDuane Sandextern ANDROID_ATOMIC_INLINE
5984c3e9923108122045d689f1d2412359ad5208ebDuane Sandvoid android_atomic_release_store(int32_t value, volatile int32_t *ptr)
6084c3e9923108122045d689f1d2412359ad5208ebDuane Sand{
6184c3e9923108122045d689f1d2412359ad5208ebDuane Sand    android_memory_barrier();
6284c3e9923108122045d689f1d2412359ad5208ebDuane Sand    *ptr = value;
6384c3e9923108122045d689f1d2412359ad5208ebDuane Sand}
6484c3e9923108122045d689f1d2412359ad5208ebDuane Sand
6584c3e9923108122045d689f1d2412359ad5208ebDuane Sandextern ANDROID_ATOMIC_INLINE
6684c3e9923108122045d689f1d2412359ad5208ebDuane Sandint android_atomic_cas(int32_t old_value, int32_t new_value, volatile int32_t *ptr)
6784c3e9923108122045d689f1d2412359ad5208ebDuane Sand{
6884c3e9923108122045d689f1d2412359ad5208ebDuane Sand    int32_t prev, status;
6984c3e9923108122045d689f1d2412359ad5208ebDuane Sand    do {
7084c3e9923108122045d689f1d2412359ad5208ebDuane Sand        __asm__ __volatile__ (
7184c3e9923108122045d689f1d2412359ad5208ebDuane Sand            "    ll     %[prev], (%[ptr])\n"
7284c3e9923108122045d689f1d2412359ad5208ebDuane Sand            "    li     %[status], 1\n"
7384c3e9923108122045d689f1d2412359ad5208ebDuane Sand            "    bne    %[prev], %[old], 9f\n"
7484c3e9923108122045d689f1d2412359ad5208ebDuane Sand            "    move   %[status], %[new_value]\n"
7584c3e9923108122045d689f1d2412359ad5208ebDuane Sand            "    sc     %[status], (%[ptr])\n"
7684c3e9923108122045d689f1d2412359ad5208ebDuane Sand            "9:\n"
7784c3e9923108122045d689f1d2412359ad5208ebDuane Sand            : [prev] "=&r" (prev), [status] "=&r" (status)
7884c3e9923108122045d689f1d2412359ad5208ebDuane Sand            : [ptr] "r" (ptr), [old] "r" (old_value), [new_value] "r" (new_value)
7984c3e9923108122045d689f1d2412359ad5208ebDuane Sand            );
8084c3e9923108122045d689f1d2412359ad5208ebDuane Sand    } while (__builtin_expect(status == 0, 0));
8184c3e9923108122045d689f1d2412359ad5208ebDuane Sand    return prev != old_value;
8284c3e9923108122045d689f1d2412359ad5208ebDuane Sand}
8384c3e9923108122045d689f1d2412359ad5208ebDuane Sand
8484c3e9923108122045d689f1d2412359ad5208ebDuane Sandextern ANDROID_ATOMIC_INLINE
8584c3e9923108122045d689f1d2412359ad5208ebDuane Sandint android_atomic_acquire_cas(int32_t old_value,
8684c3e9923108122045d689f1d2412359ad5208ebDuane Sand                           int32_t new_value,
8784c3e9923108122045d689f1d2412359ad5208ebDuane Sand                           volatile int32_t *ptr)
8884c3e9923108122045d689f1d2412359ad5208ebDuane Sand{
8984c3e9923108122045d689f1d2412359ad5208ebDuane Sand    int status = android_atomic_cas(old_value, new_value, ptr);
9084c3e9923108122045d689f1d2412359ad5208ebDuane Sand    android_memory_barrier();
9184c3e9923108122045d689f1d2412359ad5208ebDuane Sand    return status;
9284c3e9923108122045d689f1d2412359ad5208ebDuane Sand}
9384c3e9923108122045d689f1d2412359ad5208ebDuane Sand
9484c3e9923108122045d689f1d2412359ad5208ebDuane Sandextern ANDROID_ATOMIC_INLINE
9584c3e9923108122045d689f1d2412359ad5208ebDuane Sandint android_atomic_release_cas(int32_t old_value,
9684c3e9923108122045d689f1d2412359ad5208ebDuane Sand                           int32_t new_value,
9784c3e9923108122045d689f1d2412359ad5208ebDuane Sand                           volatile int32_t *ptr)
9884c3e9923108122045d689f1d2412359ad5208ebDuane Sand{
9984c3e9923108122045d689f1d2412359ad5208ebDuane Sand    android_memory_barrier();
10084c3e9923108122045d689f1d2412359ad5208ebDuane Sand    return android_atomic_cas(old_value, new_value, ptr);
10184c3e9923108122045d689f1d2412359ad5208ebDuane Sand}
10284c3e9923108122045d689f1d2412359ad5208ebDuane Sand
10384c3e9923108122045d689f1d2412359ad5208ebDuane Sandextern ANDROID_ATOMIC_INLINE
10484c3e9923108122045d689f1d2412359ad5208ebDuane Sandint32_t android_atomic_add(int32_t increment, volatile int32_t *ptr)
10584c3e9923108122045d689f1d2412359ad5208ebDuane Sand{
10684c3e9923108122045d689f1d2412359ad5208ebDuane Sand    int32_t prev, status;
10784c3e9923108122045d689f1d2412359ad5208ebDuane Sand    android_memory_barrier();
10884c3e9923108122045d689f1d2412359ad5208ebDuane Sand    do {
10984c3e9923108122045d689f1d2412359ad5208ebDuane Sand        __asm__ __volatile__ (
11084c3e9923108122045d689f1d2412359ad5208ebDuane Sand        "    ll    %[prev], (%[ptr])\n"
11184c3e9923108122045d689f1d2412359ad5208ebDuane Sand        "    addu  %[status], %[prev], %[inc]\n"
11284c3e9923108122045d689f1d2412359ad5208ebDuane Sand        "    sc    %[status], (%[ptr])\n"
11384c3e9923108122045d689f1d2412359ad5208ebDuane Sand        :  [status] "=&r" (status), [prev] "=&r" (prev)
11484c3e9923108122045d689f1d2412359ad5208ebDuane Sand        :  [ptr] "r" (ptr), [inc] "Ir" (increment)
11584c3e9923108122045d689f1d2412359ad5208ebDuane Sand        );
11684c3e9923108122045d689f1d2412359ad5208ebDuane Sand    } while (__builtin_expect(status == 0, 0));
11784c3e9923108122045d689f1d2412359ad5208ebDuane Sand    return prev;
11884c3e9923108122045d689f1d2412359ad5208ebDuane Sand}
11984c3e9923108122045d689f1d2412359ad5208ebDuane Sand
12084c3e9923108122045d689f1d2412359ad5208ebDuane Sandextern ANDROID_ATOMIC_INLINE int32_t
12184c3e9923108122045d689f1d2412359ad5208ebDuane Sandandroid_atomic_inc(volatile int32_t *addr)
12284c3e9923108122045d689f1d2412359ad5208ebDuane Sand{
12384c3e9923108122045d689f1d2412359ad5208ebDuane Sand    return android_atomic_add(1, addr);
12484c3e9923108122045d689f1d2412359ad5208ebDuane Sand}
12584c3e9923108122045d689f1d2412359ad5208ebDuane Sand
12684c3e9923108122045d689f1d2412359ad5208ebDuane Sandextern ANDROID_ATOMIC_INLINE int32_t
12784c3e9923108122045d689f1d2412359ad5208ebDuane Sandandroid_atomic_dec(volatile int32_t *addr)
12884c3e9923108122045d689f1d2412359ad5208ebDuane Sand{
12984c3e9923108122045d689f1d2412359ad5208ebDuane Sand    return android_atomic_add(-1, addr);
13084c3e9923108122045d689f1d2412359ad5208ebDuane Sand}
13184c3e9923108122045d689f1d2412359ad5208ebDuane Sand
13284c3e9923108122045d689f1d2412359ad5208ebDuane Sandextern ANDROID_ATOMIC_INLINE int32_t
13384c3e9923108122045d689f1d2412359ad5208ebDuane Sandandroid_atomic_and(int32_t value, volatile int32_t *ptr)
13484c3e9923108122045d689f1d2412359ad5208ebDuane Sand{
13584c3e9923108122045d689f1d2412359ad5208ebDuane Sand    int32_t prev, status;
13684c3e9923108122045d689f1d2412359ad5208ebDuane Sand    android_memory_barrier();
13784c3e9923108122045d689f1d2412359ad5208ebDuane Sand    do {
13884c3e9923108122045d689f1d2412359ad5208ebDuane Sand        __asm__ __volatile__ (
13984c3e9923108122045d689f1d2412359ad5208ebDuane Sand        "    ll    %[prev], (%[ptr])\n"
14084c3e9923108122045d689f1d2412359ad5208ebDuane Sand        "    and   %[status], %[prev], %[value]\n"
14184c3e9923108122045d689f1d2412359ad5208ebDuane Sand        "    sc    %[status], (%[ptr])\n"
14284c3e9923108122045d689f1d2412359ad5208ebDuane Sand        : [prev] "=&r" (prev), [status] "=&r" (status)
14384c3e9923108122045d689f1d2412359ad5208ebDuane Sand        : [ptr] "r" (ptr), [value] "Ir" (value)
14484c3e9923108122045d689f1d2412359ad5208ebDuane Sand            );
14584c3e9923108122045d689f1d2412359ad5208ebDuane Sand    } while (__builtin_expect(status == 0, 0));
14684c3e9923108122045d689f1d2412359ad5208ebDuane Sand    return prev;
14784c3e9923108122045d689f1d2412359ad5208ebDuane Sand}
14884c3e9923108122045d689f1d2412359ad5208ebDuane Sand
14984c3e9923108122045d689f1d2412359ad5208ebDuane Sandextern ANDROID_ATOMIC_INLINE int32_t
15084c3e9923108122045d689f1d2412359ad5208ebDuane Sandandroid_atomic_or(int32_t value, volatile int32_t *ptr)
15184c3e9923108122045d689f1d2412359ad5208ebDuane Sand{
15284c3e9923108122045d689f1d2412359ad5208ebDuane Sand    int32_t prev, status;
15384c3e9923108122045d689f1d2412359ad5208ebDuane Sand    android_memory_barrier();
15484c3e9923108122045d689f1d2412359ad5208ebDuane Sand    do {
15584c3e9923108122045d689f1d2412359ad5208ebDuane Sand        __asm__ __volatile__ (
15684c3e9923108122045d689f1d2412359ad5208ebDuane Sand        "    ll    %[prev], (%[ptr])\n"
15784c3e9923108122045d689f1d2412359ad5208ebDuane Sand        "    or    %[status], %[prev], %[value]\n"
15884c3e9923108122045d689f1d2412359ad5208ebDuane Sand        "    sc    %[status], (%[ptr])\n"
15984c3e9923108122045d689f1d2412359ad5208ebDuane Sand        : [prev] "=&r" (prev), [status] "=&r" (status)
16084c3e9923108122045d689f1d2412359ad5208ebDuane Sand        : [ptr] "r" (ptr), [value] "Ir" (value)
16184c3e9923108122045d689f1d2412359ad5208ebDuane Sand            );
16284c3e9923108122045d689f1d2412359ad5208ebDuane Sand    } while (__builtin_expect(status == 0, 0));
16384c3e9923108122045d689f1d2412359ad5208ebDuane Sand    return prev;
16484c3e9923108122045d689f1d2412359ad5208ebDuane Sand}
16584c3e9923108122045d689f1d2412359ad5208ebDuane Sand
16684c3e9923108122045d689f1d2412359ad5208ebDuane Sand#endif /* ANDROID_CUTILS_ATOMIC_MIPS_H */
167