< prev index next >

src/hotspot/os_cpu/linux_s390/atomic_linux_s390.hpp

Print this page




 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 


< prev index next >