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 #if defined(ANDROID_SMP) && ANDROID_SMP == 1 23 __ATOMIC_INLINE__ void 24 __bionic_memory_barrier() 25 { 26 __asm__ __volatile__ ( "sync" : : : "memory" ); 27 } 28 #else 29 __ATOMIC_INLINE__ void 30 __bionic_memory_barrier() 31 { 32 /* A simple compiler barrier */ 33 __asm__ __volatile__ ( "" : : : "memory" ); 34 } 35 #endif 36 37 /* Compare-and-swap, without any explicit barriers. Note that this function 38 * returns 0 on success, and 1 on failure. The opposite convention is typically 39 * used on other platforms. 40 */ 41 __ATOMIC_INLINE__ int 42 __bionic_cmpxchg(int32_t old_value, int32_t new_value, volatile int32_t* ptr) 43 { 44 int32_t prev, status; 45 __asm__ __volatile__ ("1: move %[status], %[new_value] \n" 46 " ll %[prev], 0(%[ptr]) \n" 47 " bne %[old_value], %[prev], 2f \n" 48 " sc %[status], 0(%[ptr]) \n" 49 " beqz %[status], 1b \n" 50 "2: \n" 51 : [prev]"=&r"(prev), [status]"=&r"(status), "+m"(*ptr) 52 : [new_value]"r"(new_value), [old_value]"r"(old_value), [ptr]"r"(ptr) 53 : "memory"); 54 return prev != old_value; 55 } 56 57 58 /* Swap, without any explicit barriers */ 59 __ATOMIC_INLINE__ int32_t 60 __bionic_swap(int32_t new_value, volatile int32_t *ptr) 61 { 62 int32_t prev, status; 63 __asm__ __volatile__ ("1: move %[status], %[new_value] \n" 64 " ll %[prev], 0(%[ptr]) \n" 65 " sc %[status], 0(%[ptr]) \n" 66 " beqz %[status], 1b \n" 67 : [prev]"=&r"(prev), [status]"=&r"(status), "+m"(*ptr) 68 : [ptr]"r"(ptr), [new_value]"r"(new_value) 69 : "memory"); 70 return prev; 71 } 72 73 /* Atomic increment, without explicit barriers */ 74 __ATOMIC_INLINE__ int32_t 75 __bionic_atomic_inc(volatile int32_t *ptr) 76 { 77 int32_t prev, status; 78 __asm__ __volatile__ ("1: ll %[prev], 0(%[ptr]) \n" 79 " addiu %[status], %[prev], 1 \n" 80 " sc %[status], 0(%[ptr]) \n" 81 " beqz %[status], 1b \n" 82 : [prev]"=&r" (prev), [status]"=&r"(status), "+m" (*ptr) 83 : [ptr]"r"(ptr) 84 : "memory"); 85 return prev; 86 } 87 88 /* Atomic decrement, without explicit barriers */ 89 __ATOMIC_INLINE__ int32_t 90 __bionic_atomic_dec(volatile int32_t *ptr) 91 { 92 int32_t prev, status; 93 __asm__ __volatile__ ("1: ll %[prev], 0(%[ptr]) \n" 94 " addiu %[status], %[prev], -1 \n" 95 " sc %[status], 0(%[ptr]) \n" 96 " beqz %[status], 1b \n" 97 : [prev]"=&r" (prev), [status]"=&r"(status), "+m" (*ptr) 98 : [ptr]"r"(ptr) 99 : "memory"); 100 return prev; 101 } 102 #endif /* BIONIC_ATOMIC_MIPS_H */ 103