src/hotspot/os_cpu/linux_zero/atomic_linux_zero.hpp
changeset 48125 4e5124dacf91
parent 47593 2d56326b98f0
child 48468 7cc7de9bf4a4
equal deleted inserted replaced
48124:f140bebf0348 48125:4e5124dacf91
    27 #define OS_CPU_LINUX_ZERO_VM_ATOMIC_LINUX_ZERO_HPP
    27 #define OS_CPU_LINUX_ZERO_VM_ATOMIC_LINUX_ZERO_HPP
    28 
    28 
    29 #include "runtime/os.hpp"
    29 #include "runtime/os.hpp"
    30 
    30 
    31 // Implementation of class atomic
    31 // Implementation of class atomic
    32 
       
    33 #ifdef M68K
       
    34 
       
    35 /*
       
    36  * __m68k_cmpxchg
       
    37  *
       
    38  * Atomically store newval in *ptr if *ptr is equal to oldval for user space.
       
    39  * Returns newval on success and oldval if no exchange happened.
       
    40  * This implementation is processor specific and works on
       
    41  * 68020 68030 68040 and 68060.
       
    42  *
       
    43  * It will not work on ColdFire, 68000 and 68010 since they lack the CAS
       
    44  * instruction.
       
    45  * Using a kernelhelper would be better for arch complete implementation.
       
    46  *
       
    47  */
       
    48 
       
    49 static inline int __m68k_cmpxchg(int oldval, int newval, volatile int *ptr) {
       
    50   int ret;
       
    51   __asm __volatile ("cas%.l %0,%2,%1"
       
    52                    : "=d" (ret), "+m" (*(ptr))
       
    53                    : "d" (newval), "0" (oldval));
       
    54   return ret;
       
    55 }
       
    56 
       
    57 /* Perform an atomic compare and swap: if the current value of `*PTR'
       
    58    is OLDVAL, then write NEWVAL into `*PTR'.  Return the contents of
       
    59    `*PTR' before the operation.*/
       
    60 static inline int m68k_compare_and_swap(int newval,
       
    61                                         volatile int *ptr,
       
    62                                         int oldval) {
       
    63   for (;;) {
       
    64       int prev = *ptr;
       
    65       if (prev != oldval)
       
    66         return prev;
       
    67 
       
    68       if (__m68k_cmpxchg (prev, newval, ptr) == newval)
       
    69         // Success.
       
    70         return prev;
       
    71 
       
    72       // We failed even though prev == oldval.  Try again.
       
    73     }
       
    74 }
       
    75 
       
    76 /* Atomically add an int to memory.  */
       
    77 static inline int m68k_add_and_fetch(int add_value, volatile int *ptr) {
       
    78   for (;;) {
       
    79       // Loop until success.
       
    80 
       
    81       int prev = *ptr;
       
    82 
       
    83       if (__m68k_cmpxchg (prev, prev + add_value, ptr) == prev + add_value)
       
    84         return prev + add_value;
       
    85     }
       
    86 }
       
    87 
       
    88 /* Atomically write VALUE into `*PTR' and returns the previous
       
    89    contents of `*PTR'.  */
       
    90 static inline int m68k_lock_test_and_set(int newval, volatile int *ptr) {
       
    91   for (;;) {
       
    92       // Loop until success.
       
    93       int prev = *ptr;
       
    94 
       
    95       if (__m68k_cmpxchg (prev, newval, ptr) == prev)
       
    96         return prev;
       
    97     }
       
    98 }
       
    99 #endif // M68K
       
   100 
    32 
   101 #ifdef ARM
    33 #ifdef ARM
   102 
    34 
   103 /*
    35 /*
   104  * __kernel_cmpxchg
    36  * __kernel_cmpxchg
   174   STATIC_ASSERT(4 == sizeof(D));
   106   STATIC_ASSERT(4 == sizeof(D));
   175 
   107 
   176 #ifdef ARM
   108 #ifdef ARM
   177   return add_using_helper<int>(arm_add_and_fetch, add_value, dest);
   109   return add_using_helper<int>(arm_add_and_fetch, add_value, dest);
   178 #else
   110 #else
   179 #ifdef M68K
       
   180   return add_using_helper<int>(m68k_add_and_fetch, add_value, dest);
       
   181 #else
       
   182   return __sync_add_and_fetch(dest, add_value);
   111   return __sync_add_and_fetch(dest, add_value);
   183 #endif // M68K
       
   184 #endif // ARM
   112 #endif // ARM
   185 }
   113 }
   186 
   114 
   187 template<>
   115 template<>
   188 template<typename I, typename D>
   116 template<typename I, typename D>
   198 inline T Atomic::PlatformXchg<4>::operator()(T exchange_value,
   126 inline T Atomic::PlatformXchg<4>::operator()(T exchange_value,
   199                                              T volatile* dest) const {
   127                                              T volatile* dest) const {
   200   STATIC_ASSERT(4 == sizeof(T));
   128   STATIC_ASSERT(4 == sizeof(T));
   201 #ifdef ARM
   129 #ifdef ARM
   202   return xchg_using_helper<int>(arm_lock_test_and_set, exchange_value, dest);
   130   return xchg_using_helper<int>(arm_lock_test_and_set, exchange_value, dest);
   203 #else
       
   204 #ifdef M68K
       
   205   return xchg_using_helper<int>(m68k_lock_test_and_set, exchange_value, dest);
       
   206 #else
   131 #else
   207   // __sync_lock_test_and_set is a bizarrely named atomic exchange
   132   // __sync_lock_test_and_set is a bizarrely named atomic exchange
   208   // operation.  Note that some platforms only support this with the
   133   // operation.  Note that some platforms only support this with the
   209   // limitation that the only valid value to store is the immediate
   134   // limitation that the only valid value to store is the immediate
   210   // constant 1.  There is a test for this in JNI_CreateJavaVM().
   135   // constant 1.  There is a test for this in JNI_CreateJavaVM().
   213   // (see atomic.hpp). However, __sync_lock_test_and_set is not
   138   // (see atomic.hpp). However, __sync_lock_test_and_set is not
   214   // a full memory barrier, but an acquire barrier. Hence, this added
   139   // a full memory barrier, but an acquire barrier. Hence, this added
   215   // barrier.
   140   // barrier.
   216   __sync_synchronize();
   141   __sync_synchronize();
   217   return result;
   142   return result;
   218 #endif // M68K
       
   219 #endif // ARM
   143 #endif // ARM
   220 }
   144 }
   221 
   145 
   222 template<>
   146 template<>
   223 template<typename T>
   147 template<typename T>
   241                                                 cmpxchg_memory_order order) const {
   165                                                 cmpxchg_memory_order order) const {
   242   STATIC_ASSERT(4 == sizeof(T));
   166   STATIC_ASSERT(4 == sizeof(T));
   243 #ifdef ARM
   167 #ifdef ARM
   244   return cmpxchg_using_helper<int>(arm_compare_and_swap, exchange_value, dest, compare_value);
   168   return cmpxchg_using_helper<int>(arm_compare_and_swap, exchange_value, dest, compare_value);
   245 #else
   169 #else
   246 #ifdef M68K
       
   247   return cmpxchg_using_helper<int>(m68k_compare_and_swap, exchange_value, dest, compare_value);
       
   248 #else
       
   249   return __sync_val_compare_and_swap(dest, compare_value, exchange_value);
   170   return __sync_val_compare_and_swap(dest, compare_value, exchange_value);
   250 #endif // M68K
       
   251 #endif // ARM
   171 #endif // ARM
   252 }
   172 }
   253 
   173 
   254 template<>
   174 template<>
   255 template<typename T>
   175 template<typename T>