1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ANDROID_CUTILS_ATOMIC_MIPS64_H 18 #define ANDROID_CUTILS_ATOMIC_MIPS64_H 19 20 #include <stdint.h> 21 22 #ifndef ANDROID_ATOMIC_INLINE 23 #define ANDROID_ATOMIC_INLINE inline __attribute__((always_inline)) 24 #endif 25 26 extern ANDROID_ATOMIC_INLINE void android_compiler_barrier(void) 27 { 28 __asm__ __volatile__ ("" : : : "memory"); 29 } 30 31 extern ANDROID_ATOMIC_INLINE void android_memory_barrier(void) 32 { 33 __asm__ __volatile__ ("sync" : : : "memory"); 34 } 35 36 extern ANDROID_ATOMIC_INLINE 37 int32_t android_atomic_acquire_load(volatile const int32_t *ptr) 38 { 39 int32_t value = *ptr; 40 android_memory_barrier(); 41 return value; 42 } 43 44 extern ANDROID_ATOMIC_INLINE 45 int32_t android_atomic_release_load(volatile const int32_t *ptr) 46 { 47 android_memory_barrier(); 48 return *ptr; 49 } 50 51 extern ANDROID_ATOMIC_INLINE 52 void android_atomic_acquire_store(int32_t value, volatile int32_t *ptr) 53 { 54 *ptr = value; 55 android_memory_barrier(); 56 } 57 58 extern ANDROID_ATOMIC_INLINE 59 void android_atomic_release_store(int32_t value, volatile int32_t *ptr) 60 { 61 android_memory_barrier(); 62 *ptr = value; 63 } 64 65 extern ANDROID_ATOMIC_INLINE 66 int android_atomic_cas(int32_t old_value, int32_t new_value, volatile int32_t *ptr) 67 { 68 int32_t prev, status; 69 do { 70 __asm__ __volatile__ ( 71 " ll %[prev], (%[ptr])\n" 72 " li %[status], 1\n" 73 " bne %[prev], %[old], 9f\n" 74 " move %[status], %[new_value]\n" 75 " sc %[status], (%[ptr])\n" 76 "9:\n" 77 : [prev] "=&r" (prev), [status] "=&r" (status) 78 : [ptr] "r" (ptr), [old] "r" (old_value), [new_value] "r" (new_value) 79 ); 80 } while (__builtin_expect(status == 0, 0)); 81 return prev != old_value; 82 } 83 84 extern ANDROID_ATOMIC_INLINE 85 int android_atomic_acquire_cas(int32_t old_value, 86 int32_t new_value, 87 volatile int32_t *ptr) 88 { 89 int status = android_atomic_cas(old_value, new_value, ptr); 90 android_memory_barrier(); 91 return status; 92 } 93 94 extern ANDROID_ATOMIC_INLINE 95 int android_atomic_release_cas(int32_t old_value, 96 int32_t new_value, 97 volatile int32_t *ptr) 98 { 99 android_memory_barrier(); 100 return android_atomic_cas(old_value, new_value, ptr); 101 } 102 103 extern ANDROID_ATOMIC_INLINE 104 int32_t android_atomic_add(int32_t increment, volatile int32_t *ptr) 105 { 106 int32_t prev, status; 107 android_memory_barrier(); 108 do { 109 __asm__ __volatile__ ( 110 " ll %[prev], (%[ptr])\n" 111 " addu %[status], %[prev], %[inc]\n" 112 " sc %[status], (%[ptr])\n" 113 : [status] "=&r" (status), [prev] "=&r" (prev) 114 : [ptr] "r" (ptr), [inc] "Ir" (increment) 115 ); 116 } while (__builtin_expect(status == 0, 0)); 117 return prev; 118 } 119 120 extern ANDROID_ATOMIC_INLINE int32_t 121 android_atomic_inc(volatile int32_t *addr) 122 { 123 return android_atomic_add(1, addr); 124 } 125 126 extern ANDROID_ATOMIC_INLINE int32_t 127 android_atomic_dec(volatile int32_t *addr) 128 { 129 return android_atomic_add(-1, addr); 130 } 131 132 extern ANDROID_ATOMIC_INLINE int32_t 133 android_atomic_and(int32_t value, volatile int32_t *ptr) 134 { 135 int32_t prev, status; 136 android_memory_barrier(); 137 do { 138 __asm__ __volatile__ ( 139 " ll %[prev], (%[ptr])\n" 140 " and %[status], %[prev], %[value]\n" 141 " sc %[status], (%[ptr])\n" 142 : [prev] "=&r" (prev), [status] "=&r" (status) 143 : [ptr] "r" (ptr), [value] "Ir" (value) 144 ); 145 } while (__builtin_expect(status == 0, 0)); 146 return prev; 147 } 148 149 extern ANDROID_ATOMIC_INLINE int32_t 150 android_atomic_or(int32_t value, volatile int32_t *ptr) 151 { 152 int32_t prev, status; 153 android_memory_barrier(); 154 do { 155 __asm__ __volatile__ ( 156 " ll %[prev], (%[ptr])\n" 157 " or %[status], %[prev], %[value]\n" 158 " sc %[status], (%[ptr])\n" 159 : [prev] "=&r" (prev), [status] "=&r" (status) 160 : [ptr] "r" (ptr), [value] "Ir" (value) 161 ); 162 } while (__builtin_expect(status == 0, 0)); 163 return prev; 164 } 165 166 #endif /* ANDROID_CUTILS_ATOMIC_MIPS_H */ 167