1 /* 2 * Copyright (C) 2016 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 #include <atomic.h> 18 19 uint32_t atomicAddByte(volatile uint8_t *byte, uint32_t addend) 20 { 21 uint32_t prevVal, storeFailed, tmp; 22 23 do { 24 asm volatile( 25 "ldrexb %0, [%4] \n" 26 "add %2, %0, %3 \n" 27 "strexb %1, %2, [%4] \n" 28 :"=r"(prevVal), "=r"(storeFailed), "=r"(tmp), "=r"(addend), "=r"(byte) 29 :"3"(addend), "4"(byte) 30 :"memory" 31 ); 32 } while (storeFailed); 33 34 return prevVal; 35 } 36 37 uint32_t atomicAdd32bits(volatile uint32_t *word, uint32_t addend) 38 { 39 uint32_t prevVal, storeFailed, tmp; 40 41 do { 42 asm volatile( 43 "ldrex %0, [%4] \n" 44 "add %2, %0, %3 \n" 45 "strex %1, %2, [%4] \n" 46 :"=r"(prevVal), "=r"(storeFailed), "=r"(tmp), "=r"(addend), "=r"(word) 47 :"3"(addend), "4"(word) 48 :"memory" 49 ); 50 } while (storeFailed); 51 52 return prevVal; 53 } 54 55 uint32_t atomicXchgByte(volatile uint8_t *byte, uint32_t newVal) 56 { 57 uint32_t prevVal, storeFailed; 58 59 do { 60 asm volatile( 61 "ldrexb %0, [%3] \n" 62 "strexb %1, %2, [%3] \n" 63 :"=r"(prevVal), "=r"(storeFailed), "=r"(newVal), "=r"(byte) 64 :"2"(newVal), "3"(byte) 65 :"memory" 66 ); 67 } while (storeFailed); 68 69 return prevVal; 70 } 71 72 uint32_t atomicXchg32bits(volatile uint32_t *word, uint32_t newVal) 73 { 74 uint32_t prevVal, storeFailed; 75 76 do { 77 asm volatile( 78 "ldrex %0, [%3] \n" 79 "strex %1, %2, [%3] \n" 80 :"=r"(prevVal), "=r"(storeFailed), "=r"(newVal), "=r"(word) 81 :"2"(newVal), "3"(word) 82 :"memory" 83 ); 84 } while (storeFailed); 85 86 return prevVal; 87 } 88 89 bool atomicCmpXchgByte(volatile uint8_t *byte, uint32_t prevVal, uint32_t newVal) 90 { 91 uint32_t currVal, storeFailed; 92 93 do { 94 asm volatile( 95 "ldrexb %0, [%1] \n" 96 :"=r"(currVal), "=r"(byte) 97 :"1"(byte) 98 :"memory" 99 ); 100 101 if (currVal != prevVal) 102 return false; 103 104 asm volatile( 105 "strexb %0, %1, [%2] \n" 106 :"=r"(storeFailed), "=r"(newVal), "=r"(byte) 107 :"1"(newVal), "2"(byte) 108 :"memory" 109 ); 110 } while (storeFailed); 111 112 return true; 113 } 114 115 bool atomicCmpXchg32bits(volatile uint32_t *word, uint32_t prevVal, uint32_t newVal) 116 { 117 uint32_t currVal, storeFailed; 118 119 do { 120 asm volatile( 121 "ldrex %0, [%1] \n" 122 :"=r"(currVal), "=r"(word) 123 :"1"(word) 124 :"memory" 125 ); 126 127 if (currVal != prevVal) 128 return false; 129 130 asm volatile( 131 "strex %0, %1, [%2] \n" 132 :"=r"(storeFailed), "=r"(newVal), "=r"(word) 133 :"1"(newVal), "2"(word) 134 :"memory" 135 ); 136 } while (storeFailed); 137 138 return true; 139 } 140