191 192 193 //------------- 194 // Atomic::xchg 195 //------------- 196 // These methods force the value in memory to be replaced by the new value passed 197 // in as argument. 198 // 199 // The value in memory is replaced by using a compare-and-swap instruction. The 200 // instruction is retried as often as required. This makes sure that the new 201 // value can be seen, at least for a very short period of time, by other CPUs. 202 // 203 // If we would use a normal "load(old value) store(new value)" sequence, 204 // the new value could be lost unnoticed, due to a store(new value) from 205 // another thread. 206 // 207 // The return value is the (unchanged) value from memory as it was when the 208 // replacement succeeded. 209 template<> 210 template<typename T> 211 inline T Atomic::PlatformXchg<4>::operator()(T exchange_value, 212 T volatile* dest, 213 atomic_memory_order unused) const { 214 STATIC_ASSERT(4 == sizeof(T)); 215 T old; 216 217 __asm__ __volatile__ ( 218 " LLGF %[old],%[mem] \n\t" // get old value 219 "0: CS %[old],%[upd],%[mem] \n\t" // try to xchg upd with mem 220 " JNE 0b \n\t" // no success? -> retry 221 //---< outputs >--- 222 : [old] "=&d" (old) // write-only, prev value irrelevant 223 , [mem] "+Q" (*dest) // read/write, memory to be updated atomically 224 //---< inputs >--- 225 : [upd] "d" (exchange_value) // read-only, value to be written to memory 226 //---< clobbered >--- 227 : "cc", "memory" 228 ); 229 230 return old; 231 } 232 233 template<> 234 template<typename T> 235 inline T Atomic::PlatformXchg<8>::operator()(T exchange_value, 236 T volatile* dest, 237 atomic_memory_order unused) const { 238 STATIC_ASSERT(8 == sizeof(T)); 239 T old; 240 241 __asm__ __volatile__ ( 242 " LG %[old],%[mem] \n\t" // get old value 243 "0: CSG %[old],%[upd],%[mem] \n\t" // try to xchg upd with mem 244 " JNE 0b \n\t" // no success? -> retry 245 //---< outputs >--- 246 : [old] "=&d" (old) // write-only, init from memory 247 , [mem] "+Q" (*dest) // read/write, memory to be updated atomically 248 //---< inputs >--- 249 : [upd] "d" (exchange_value) // read-only, value to be written to memory 250 //---< clobbered >--- 251 : "cc", "memory" 252 ); 253 254 return old; 255 } 256 | 191 192 193 //------------- 194 // Atomic::xchg 195 //------------- 196 // These methods force the value in memory to be replaced by the new value passed 197 // in as argument. 198 // 199 // The value in memory is replaced by using a compare-and-swap instruction. The 200 // instruction is retried as often as required. This makes sure that the new 201 // value can be seen, at least for a very short period of time, by other CPUs. 202 // 203 // If we would use a normal "load(old value) store(new value)" sequence, 204 // the new value could be lost unnoticed, due to a store(new value) from 205 // another thread. 206 // 207 // The return value is the (unchanged) value from memory as it was when the 208 // replacement succeeded. 209 template<> 210 template<typename T> 211 inline T Atomic::PlatformXchg<4>::operator()(T volatile* dest, 212 T exchange_value, 213 atomic_memory_order unused) const { 214 STATIC_ASSERT(4 == sizeof(T)); 215 T old; 216 217 __asm__ __volatile__ ( 218 " LLGF %[old],%[mem] \n\t" // get old value 219 "0: CS %[old],%[upd],%[mem] \n\t" // try to xchg upd with mem 220 " JNE 0b \n\t" // no success? -> retry 221 //---< outputs >--- 222 : [old] "=&d" (old) // write-only, prev value irrelevant 223 , [mem] "+Q" (*dest) // read/write, memory to be updated atomically 224 //---< inputs >--- 225 : [upd] "d" (exchange_value) // read-only, value to be written to memory 226 //---< clobbered >--- 227 : "cc", "memory" 228 ); 229 230 return old; 231 } 232 233 template<> 234 template<typename T> 235 inline T Atomic::PlatformXchg<8>::operator()(T volatile* dest, 236 T exchange_value, 237 atomic_memory_order unused) const { 238 STATIC_ASSERT(8 == sizeof(T)); 239 T old; 240 241 __asm__ __volatile__ ( 242 " LG %[old],%[mem] \n\t" // get old value 243 "0: CSG %[old],%[upd],%[mem] \n\t" // try to xchg upd with mem 244 " JNE 0b \n\t" // no success? -> retry 245 //---< outputs >--- 246 : [old] "=&d" (old) // write-only, init from memory 247 , [mem] "+Q" (*dest) // read/write, memory to be updated atomically 248 //---< inputs >--- 249 : [upd] "d" (exchange_value) // read-only, value to be written to memory 250 //---< clobbered >--- 251 : "cc", "memory" 252 ); 253 254 return old; 255 } 256 |