1 /* 2 * Copyright (C) 2011 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 #ifndef BIONIC_ATOMIC_MIPS_H 17 #define BIONIC_ATOMIC_MIPS_H 18 19 /* Define a full memory barrier, this is only needed if we build the 20 * platform for a multi-core device. 21 */ 22 23 __ATOMIC_INLINE__ void __bionic_memory_barrier() { 24 #if defined(ANDROID_SMP) && ANDROID_SMP == 1 25 __asm__ __volatile__ ( "sync" : : : "memory" ); 26 #else 27 /* A simple compiler barrier. */ 28 __asm__ __volatile__ ( "" : : : "memory" ); 29 #endif 30 } 31 32 /* Compare-and-swap, without any explicit barriers. Note that this function 33 * returns 0 on success, and 1 on failure. The opposite convention is typically 34 * used on other platforms. 35 */ 36 __ATOMIC_INLINE__ int __bionic_cmpxchg(int32_t old_value, int32_t new_value, volatile int32_t* ptr) { 37 int32_t prev, status; 38 __asm__ __volatile__ ("1: move %[status], %[new_value] \n" 39 " ll %[prev], 0(%[ptr]) \n" 40 " bne %[old_value], %[prev], 2f \n" 41 " sc %[status], 0(%[ptr]) \n" 42 " beqz %[status], 1b \n" 43 "2: \n" 44 : [prev]"=&r"(prev), [status]"=&r"(status), "+m"(*ptr) 45 : [new_value]"r"(new_value), [old_value]"r"(old_value), [ptr]"r"(ptr) 46 : "memory"); 47 return prev != old_value; 48 } 49 50 /* Swap, without any explicit barriers. */ 51 __ATOMIC_INLINE__ int32_t __bionic_swap(int32_t new_value, volatile int32_t* ptr) { 52 int32_t prev, status; 53 __asm__ __volatile__ ("1: move %[status], %[new_value] \n" 54 " ll %[prev], 0(%[ptr]) \n" 55 " sc %[status], 0(%[ptr]) \n" 56 " beqz %[status], 1b \n" 57 : [prev]"=&r"(prev), [status]"=&r"(status), "+m"(*ptr) 58 : [ptr]"r"(ptr), [new_value]"r"(new_value) 59 : "memory"); 60 return prev; 61 } 62 63 /* Atomic decrement, without explicit barriers. */ 64 __ATOMIC_INLINE__ int32_t __bionic_atomic_dec(volatile int32_t* ptr) { 65 int32_t prev, status; 66 __asm__ __volatile__ ("1: ll %[prev], 0(%[ptr]) \n" 67 " addiu %[status], %[prev], -1 \n" 68 " sc %[status], 0(%[ptr]) \n" 69 " beqz %[status], 1b \n" 70 : [prev]"=&r" (prev), [status]"=&r"(status), "+m" (*ptr) 71 : [ptr]"r"(ptr) 72 : "memory"); 73 return prev; 74 } 75 76 #endif /* BIONIC_ATOMIC_MIPS_H */ 77