< prev index next >

src/os_cpu/linux_s390/vm/atomic_linux_s390.hpp

Print this page
rev 13452 : imported patch Atomic_cmpxchg
rev 13453 : imported patch Atomic_add
rev 13454 : [mq]: Atomic_add_v2


  65 inline void Atomic::store    (jint     store_value, volatile jint*     dest) { *dest = store_value; }
  66 inline void Atomic::store    (jlong    store_value, volatile jlong*    dest) { *dest = store_value; }
  67 inline void Atomic::store_ptr(intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; }
  68 inline void Atomic::store_ptr(void*    store_value, volatile void*     dest) { *(void* volatile *)dest = store_value; }
  69 
  70 
  71 //------------
  72 // Atomic::add
  73 //------------
  74 // These methods force the value in memory to be augmented by the passed increment.
  75 // Both, memory value and increment, are treated as 32bit signed binary integers.
  76 // No overflow exceptions are recognized, and the condition code does not hold
  77 // information about the value in memory.
  78 //
  79 // The value in memory is updated by using a compare-and-swap instruction. The
  80 // instruction is retried as often as required.
  81 //
  82 // The return value of the method is the value that was successfully stored. At the
  83 // time the caller receives back control, the value in memory may have changed already.
  84 
  85 inline jint Atomic::add(jint inc, volatile jint*dest) {
  86   unsigned int old, upd;













  87 
  88   if (VM_Version::has_LoadAndALUAtomicV1()) {
  89     __asm__ __volatile__ (
  90       "   LGFR     0,%[inc]                \n\t" // save increment
  91       "   LA       3,%[mem]                \n\t" // force data address into ARG2
  92 //    "   LAA      %[upd],%[inc],%[mem]    \n\t" // increment and get old value
  93 //    "   LAA      2,0,0(3)                \n\t" // actually coded instruction
  94       "   .byte    0xeb                    \n\t" // LAA main opcode
  95       "   .byte    0x20                    \n\t" // R1,R3
  96       "   .byte    0x30                    \n\t" // R2,disp1
  97       "   .byte    0x00                    \n\t" // disp2,disp3
  98       "   .byte    0x00                    \n\t" // disp4,disp5
  99       "   .byte    0xf8                    \n\t" // LAA minor opcode
 100       "   AR       2,0                     \n\t" // calc new value in register
 101       "   LR       %[upd],2                \n\t" // move to result register
 102       //---<  outputs  >---
 103       : [upd]  "=&d" (upd)    // write-only, updated counter value
 104       , [mem]  "+Q"  (*dest)  // read/write, memory to be updated atomically
 105       //---<  inputs  >---
 106       : [inc]  "a"   (inc)    // read-only.
 107       //---<  clobbered  >---
 108       : "cc", "r0", "r2", "r3"
 109     );
 110   } else {
 111     __asm__ __volatile__ (
 112       "   LLGF     %[old],%[mem]           \n\t" // get old value
 113       "0: LA       %[upd],0(%[inc],%[old]) \n\t" // calc result
 114       "   CS       %[old],%[upd],%[mem]    \n\t" // try to xchg res with mem
 115       "   JNE      0b                      \n\t" // no success? -> retry
 116       //---<  outputs  >---
 117       : [old] "=&a" (old)    // write-only, old counter value
 118       , [upd] "=&d" (upd)    // write-only, updated counter value
 119       , [mem] "+Q"  (*dest)  // read/write, memory to be updated atomically
 120       //---<  inputs  >---
 121       : [inc] "a"   (inc)    // read-only.
 122       //---<  clobbered  >---
 123       : "cc"
 124     );
 125   }
 126 
 127   return (jint)upd;
 128 }
 129 
 130 
 131 inline intptr_t Atomic::add_ptr(intptr_t inc, volatile intptr_t* dest) {
 132   unsigned long old, upd;





 133 
 134   if (VM_Version::has_LoadAndALUAtomicV1()) {
 135     __asm__ __volatile__ (
 136       "   LGR      0,%[inc]                \n\t" // save increment
 137       "   LA       3,%[mem]                \n\t" // force data address into ARG2
 138 //    "   LAAG     %[upd],%[inc],%[mem]    \n\t" // increment and get old value
 139 //    "   LAAG     2,0,0(3)                \n\t" // actually coded instruction
 140       "   .byte    0xeb                    \n\t" // LAA main opcode
 141       "   .byte    0x20                    \n\t" // R1,R3
 142       "   .byte    0x30                    \n\t" // R2,disp1
 143       "   .byte    0x00                    \n\t" // disp2,disp3
 144       "   .byte    0x00                    \n\t" // disp4,disp5
 145       "   .byte    0xe8                    \n\t" // LAA minor opcode
 146       "   AGR      2,0                     \n\t" // calc new value in register
 147       "   LGR      %[upd],2                \n\t" // move to result register
 148       //---<  outputs  >---
 149       : [upd]  "=&d" (upd)    // write-only, updated counter value
 150       , [mem]  "+Q"  (*dest)  // read/write, memory to be updated atomically
 151       //---<  inputs  >---
 152       : [inc]  "a"   (inc)    // read-only.
 153       //---<  clobbered  >---
 154       : "cc", "r0", "r2", "r3"
 155     );
 156   } else {
 157     __asm__ __volatile__ (
 158       "   LG       %[old],%[mem]           \n\t" // get old value
 159       "0: LA       %[upd],0(%[inc],%[old]) \n\t" // calc result
 160       "   CSG      %[old],%[upd],%[mem]    \n\t" // try to xchg res with mem
 161       "   JNE      0b                      \n\t" // no success? -> retry
 162       //---<  outputs  >---
 163       : [old] "=&a" (old)    // write-only, old counter value
 164       , [upd] "=&d" (upd)    // write-only, updated counter value
 165       , [mem] "+Q"  (*dest)  // read/write, memory to be updated atomically
 166       //---<  inputs  >---
 167       : [inc] "a"   (inc)    // read-only.
 168       //---<  clobbered  >---
 169       : "cc"
 170     );
 171   }
 172 
 173   return (intptr_t)upd;
 174 }
 175 
 176 inline void* Atomic::add_ptr(intptr_t add_value, volatile void* dest) {
 177   return (void*)add_ptr(add_value, (volatile intptr_t*)dest);
 178 }
 179 


 180 
 181 //------------
 182 // Atomic::inc
 183 //------------
 184 // These methods force the value in memory to be incremented (augmented by 1).
 185 // Both, memory value and increment, are treated as 32bit signed binary integers.
 186 // No overflow exceptions are recognized, and the condition code does not hold
 187 // information about the value in memory.
 188 //
 189 // The value in memory is updated by using a compare-and-swap instruction. The
 190 // instruction is retried as often as required.
 191 
 192 inline void Atomic::inc(volatile jint* dest) {
 193   unsigned int old, upd;
 194 
 195   if (VM_Version::has_LoadAndALUAtomicV1()) {
 196 //  tty->print_cr("Atomic::inc     called... dest @%p", dest);
 197     __asm__ __volatile__ (
 198       "   LGHI     2,1                     \n\t" // load increment
 199       "   LA       3,%[mem]                \n\t" // force data address into ARG2




  65 inline void Atomic::store    (jint     store_value, volatile jint*     dest) { *dest = store_value; }
  66 inline void Atomic::store    (jlong    store_value, volatile jlong*    dest) { *dest = store_value; }
  67 inline void Atomic::store_ptr(intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; }
  68 inline void Atomic::store_ptr(void*    store_value, volatile void*     dest) { *(void* volatile *)dest = store_value; }
  69 
  70 
  71 //------------
  72 // Atomic::add
  73 //------------
  74 // These methods force the value in memory to be augmented by the passed increment.
  75 // Both, memory value and increment, are treated as 32bit signed binary integers.
  76 // No overflow exceptions are recognized, and the condition code does not hold
  77 // information about the value in memory.
  78 //
  79 // The value in memory is updated by using a compare-and-swap instruction. The
  80 // instruction is retried as often as required.
  81 //
  82 // The return value of the method is the value that was successfully stored. At the
  83 // time the caller receives back control, the value in memory may have changed already.
  84 
  85 template<size_t byte_size>
  86 struct Atomic::PlatformAdd
  87   : Atomic::AddAndFetch<Atomic::PlatformAdd<byte_size> >
  88 {
  89   template<typename I, typename D>
  90   D add_and_fetch(I add_value, D volatile* dest) const;
  91 };
  92 
  93 template<>
  94 template<typename I, typename D>
  95 inline D Atomic::PlatformAdd<4>::add_and_fetch(I add_value, D volatile* dest) const {
  96   STATIC_CAST(4 == sizeof(I));
  97   STATIC_CAST(4 == sizeof(D));
  98 
  99   D old, upd;
 100 
 101   if (VM_Version::has_LoadAndALUAtomicV1()) {
 102     __asm__ __volatile__ (
 103       "   LGFR     0,%[inc]                \n\t" // save increment
 104       "   LA       3,%[mem]                \n\t" // force data address into ARG2
 105 //    "   LAA      %[upd],%[inc],%[mem]    \n\t" // increment and get old value
 106 //    "   LAA      2,0,0(3)                \n\t" // actually coded instruction
 107       "   .byte    0xeb                    \n\t" // LAA main opcode
 108       "   .byte    0x20                    \n\t" // R1,R3
 109       "   .byte    0x30                    \n\t" // R2,disp1
 110       "   .byte    0x00                    \n\t" // disp2,disp3
 111       "   .byte    0x00                    \n\t" // disp4,disp5
 112       "   .byte    0xf8                    \n\t" // LAA minor opcode
 113       "   AR       2,0                     \n\t" // calc new value in register
 114       "   LR       %[upd],2                \n\t" // move to result register
 115       //---<  outputs  >---
 116       : [upd]  "=&d" (upd)    // write-only, updated counter value
 117       , [mem]  "+Q"  (*dest)  // read/write, memory to be updated atomically
 118       //---<  inputs  >---
 119       : [inc]  "a"   (inc)    // read-only.
 120       //---<  clobbered  >---
 121       : "cc", "r0", "r2", "r3"
 122     );
 123   } else {
 124     __asm__ __volatile__ (
 125       "   LLGF     %[old],%[mem]           \n\t" // get old value
 126       "0: LA       %[upd],0(%[inc],%[old]) \n\t" // calc result
 127       "   CS       %[old],%[upd],%[mem]    \n\t" // try to xchg res with mem
 128       "   JNE      0b                      \n\t" // no success? -> retry
 129       //---<  outputs  >---
 130       : [old] "=&a" (old)    // write-only, old counter value
 131       , [upd] "=&d" (upd)    // write-only, updated counter value
 132       , [mem] "+Q"  (*dest)  // read/write, memory to be updated atomically
 133       //---<  inputs  >---
 134       : [inc] "a"   (inc)    // read-only.
 135       //---<  clobbered  >---
 136       : "cc"
 137     );
 138   }
 139 
 140   return upd;
 141 }
 142 
 143 
 144 template<>
 145 template<typename I, typename D>
 146 inline D Atomic::PlatformAdd<8>::add_and_fetch(I add_value, D volatile* dest) const {
 147   STATIC_CAST(8 == sizeof(I));
 148   STATIC_CAST(8 == sizeof(D));
 149 
 150   D old, upd;
 151 
 152   if (VM_Version::has_LoadAndALUAtomicV1()) {
 153     __asm__ __volatile__ (
 154       "   LGR      0,%[inc]                \n\t" // save increment
 155       "   LA       3,%[mem]                \n\t" // force data address into ARG2
 156 //    "   LAAG     %[upd],%[inc],%[mem]    \n\t" // increment and get old value
 157 //    "   LAAG     2,0,0(3)                \n\t" // actually coded instruction
 158       "   .byte    0xeb                    \n\t" // LAA main opcode
 159       "   .byte    0x20                    \n\t" // R1,R3
 160       "   .byte    0x30                    \n\t" // R2,disp1
 161       "   .byte    0x00                    \n\t" // disp2,disp3
 162       "   .byte    0x00                    \n\t" // disp4,disp5
 163       "   .byte    0xe8                    \n\t" // LAA minor opcode
 164       "   AGR      2,0                     \n\t" // calc new value in register
 165       "   LGR      %[upd],2                \n\t" // move to result register
 166       //---<  outputs  >---
 167       : [upd]  "=&d" (upd)    // write-only, updated counter value
 168       , [mem]  "+Q"  (*dest)  // read/write, memory to be updated atomically
 169       //---<  inputs  >---
 170       : [inc]  "a"   (inc)    // read-only.
 171       //---<  clobbered  >---
 172       : "cc", "r0", "r2", "r3"
 173     );
 174   } else {
 175     __asm__ __volatile__ (
 176       "   LG       %[old],%[mem]           \n\t" // get old value
 177       "0: LA       %[upd],0(%[inc],%[old]) \n\t" // calc result
 178       "   CSG      %[old],%[upd],%[mem]    \n\t" // try to xchg res with mem
 179       "   JNE      0b                      \n\t" // no success? -> retry
 180       //---<  outputs  >---
 181       : [old] "=&a" (old)    // write-only, old counter value
 182       , [upd] "=&d" (upd)    // write-only, updated counter value
 183       , [mem] "+Q"  (*dest)  // read/write, memory to be updated atomically
 184       //---<  inputs  >---
 185       : [inc] "a"   (inc)    // read-only.
 186       //---<  clobbered  >---
 187       : "cc"
 188     );
 189   }
 190 
 191   return upd;




 192 }
 193 
 194 template<>
 195 struct Atomic::PlatformAdd<2>: Atomic::AddShortUsingInt {};
 196 
 197 //------------
 198 // Atomic::inc
 199 //------------
 200 // These methods force the value in memory to be incremented (augmented by 1).
 201 // Both, memory value and increment, are treated as 32bit signed binary integers.
 202 // No overflow exceptions are recognized, and the condition code does not hold
 203 // information about the value in memory.
 204 //
 205 // The value in memory is updated by using a compare-and-swap instruction. The
 206 // instruction is retried as often as required.
 207 
 208 inline void Atomic::inc(volatile jint* dest) {
 209   unsigned int old, upd;
 210 
 211   if (VM_Version::has_LoadAndALUAtomicV1()) {
 212 //  tty->print_cr("Atomic::inc     called... dest @%p", dest);
 213     __asm__ __volatile__ (
 214       "   LGHI     2,1                     \n\t" // load increment
 215       "   LA       3,%[mem]                \n\t" // force data address into ARG2


< prev index next >