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_MIPS_H 18#define ANDROID_CUTILS_ATOMIC_MIPS_H 19 20#include <stdint.h> 21 22extern inline void android_compiler_barrier(void) 23{ 24 __asm__ __volatile__ ("" : : : "memory"); 25} 26 27#if ANDROID_SMP == 0 28extern inline void android_memory_barrier(void) 29{ 30 android_compiler_barrier(); 31} 32extern inline void android_memory_store_barrier(void) 33{ 34 android_compiler_barrier(); 35} 36#else 37extern inline void android_memory_barrier(void) 38{ 39 __asm__ __volatile__ ("sync" : : : "memory"); 40} 41extern inline void android_memory_store_barrier(void) 42{ 43 __asm__ __volatile__ ("sync" : : : "memory"); 44} 45#endif 46 47extern inline int32_t android_atomic_acquire_load(volatile const int32_t *ptr) 48{ 49 int32_t value = *ptr; 50 android_memory_barrier(); 51 return value; 52} 53 54extern inline int32_t android_atomic_release_load(volatile const int32_t *ptr) 55{ 56 android_memory_barrier(); 57 return *ptr; 58} 59 60extern inline void android_atomic_acquire_store(int32_t value, 61 volatile int32_t *ptr) 62{ 63 *ptr = value; 64 android_memory_barrier(); 65} 66 67extern inline void android_atomic_release_store(int32_t value, 68 volatile int32_t *ptr) 69{ 70 android_memory_barrier(); 71 *ptr = value; 72} 73 74extern inline int android_atomic_cas(int32_t old_value, int32_t new_value, 75 volatile int32_t *ptr) 76{ 77 int32_t prev, status; 78 do { 79 __asm__ __volatile__ ( 80 " ll %[prev], (%[ptr])\n" 81 " li %[status], 1\n" 82 " bne %[prev], %[old], 9f\n" 83 " move %[status], %[new_value]\n" 84 " sc %[status], (%[ptr])\n" 85 "9:\n" 86 : [prev] "=&r" (prev), [status] "=&r" (status) 87 : [ptr] "r" (ptr), [old] "r" (old_value), [new_value] "r" (new_value) 88 ); 89 } while (__builtin_expect(status == 0, 0)); 90 return prev != old_value; 91} 92 93extern inline int android_atomic_acquire_cas(int32_t old_value, 94 int32_t new_value, 95 volatile int32_t *ptr) 96{ 97 int status = android_atomic_cas(old_value, new_value, ptr); 98 android_memory_barrier(); 99 return status; 100} 101 102extern inline int android_atomic_release_cas(int32_t old_value, 103 int32_t new_value, 104 volatile int32_t *ptr) 105{ 106 android_memory_barrier(); 107 return android_atomic_cas(old_value, new_value, ptr); 108} 109 110 111extern inline int32_t android_atomic_swap(int32_t new_value, 112 volatile int32_t *ptr) 113{ 114 int32_t prev, status; 115 do { 116 __asm__ __volatile__ ( 117 " move %[status], %[new_value]\n" 118 " ll %[prev], (%[ptr])\n" 119 " sc %[status], (%[ptr])\n" 120 : [prev] "=&r" (prev), [status] "=&r" (status) 121 : [ptr] "r" (ptr), [new_value] "r" (new_value) 122 ); 123 } while (__builtin_expect(status == 0, 0)); 124 android_memory_barrier(); 125 return prev; 126} 127 128extern inline int32_t android_atomic_add(int32_t increment, 129 volatile int32_t *ptr) 130{ 131 int32_t prev, status; 132 android_memory_barrier(); 133 do { 134 __asm__ __volatile__ ( 135 " ll %[prev], (%[ptr])\n" 136 " addu %[status], %[prev], %[inc]\n" 137 " sc %[status], (%[ptr])\n" 138 : [status] "=&r" (status), [prev] "=&r" (prev) 139 : [ptr] "r" (ptr), [inc] "Ir" (increment) 140 ); 141 } while (__builtin_expect(status == 0, 0)); 142 return prev; 143} 144 145extern inline int32_t android_atomic_inc(volatile int32_t *addr) 146{ 147 return android_atomic_add(1, addr); 148} 149 150extern inline int32_t android_atomic_dec(volatile int32_t *addr) 151{ 152 return android_atomic_add(-1, addr); 153} 154 155extern inline int32_t android_atomic_and(int32_t value, volatile int32_t *ptr) 156{ 157 int32_t prev, status; 158 android_memory_barrier(); 159 do { 160 __asm__ __volatile__ ( 161 " ll %[prev], (%[ptr])\n" 162 " and %[status], %[prev], %[value]\n" 163 " sc %[status], (%[ptr])\n" 164 : [prev] "=&r" (prev), [status] "=&r" (status) 165 : [ptr] "r" (ptr), [value] "Ir" (value) 166 ); 167 } while (__builtin_expect(status == 0, 0)); 168 return prev; 169} 170 171extern inline int32_t android_atomic_or(int32_t value, volatile int32_t *ptr) 172{ 173 int32_t prev, status; 174 android_memory_barrier(); 175 do { 176 __asm__ __volatile__ ( 177 " ll %[prev], (%[ptr])\n" 178 " or %[status], %[prev], %[value]\n" 179 " sc %[status], (%[ptr])\n" 180 : [prev] "=&r" (prev), [status] "=&r" (status) 181 : [ptr] "r" (ptr), [value] "Ir" (value) 182 ); 183 } while (__builtin_expect(status == 0, 0)); 184 return prev; 185} 186 187#endif /* ANDROID_CUTILS_ATOMIC_MIPS_H */ 188