src/os_cpu/solaris_sparc/vm/atomic_solaris_sparc.inline.hpp

Fri, 07 Dec 2012 01:09:03 -0800

author
roland
date
Fri, 07 Dec 2012 01:09:03 -0800
changeset 4325
d2f8c38e543d
parent 2557
f7de3327c683
child 4675
63e54c37ac64
permissions
-rw-r--r--

Merge

     1 /*
     2  * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  *
    23  */
    25 #ifndef OS_CPU_SOLARIS_SPARC_VM_ATOMIC_SOLARIS_SPARC_INLINE_HPP
    26 #define OS_CPU_SOLARIS_SPARC_VM_ATOMIC_SOLARIS_SPARC_INLINE_HPP
    28 #include "orderAccess_solaris_sparc.inline.hpp"
    29 #include "runtime/atomic.hpp"
    30 #include "runtime/os.hpp"
    31 #include "vm_version_sparc.hpp"
    33 // Implementation of class atomic
    35 inline void Atomic::store    (jbyte    store_value, jbyte*    dest) { *dest = store_value; }
    36 inline void Atomic::store    (jshort   store_value, jshort*   dest) { *dest = store_value; }
    37 inline void Atomic::store    (jint     store_value, jint*     dest) { *dest = store_value; }
    38 inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest) { *dest = store_value; }
    39 inline void Atomic::store_ptr(void*    store_value, void*     dest) { *(void**)dest = store_value; }
    41 inline void Atomic::store    (jbyte    store_value, volatile jbyte*    dest) { *dest = store_value; }
    42 inline void Atomic::store    (jshort   store_value, volatile jshort*   dest) { *dest = store_value; }
    43 inline void Atomic::store    (jint     store_value, volatile jint*     dest) { *dest = store_value; }
    44 inline void Atomic::store_ptr(intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; }
    45 inline void Atomic::store_ptr(void*    store_value, volatile void*     dest) { *(void* volatile *)dest = store_value; }
    47 inline void Atomic::inc    (volatile jint*     dest) { (void)add    (1, dest); }
    48 inline void Atomic::inc_ptr(volatile intptr_t* dest) { (void)add_ptr(1, dest); }
    49 inline void Atomic::inc_ptr(volatile void*     dest) { (void)add_ptr(1, dest); }
    51 inline void Atomic::dec    (volatile jint*     dest) { (void)add    (-1, dest); }
    52 inline void Atomic::dec_ptr(volatile intptr_t* dest) { (void)add_ptr(-1, dest); }
    53 inline void Atomic::dec_ptr(volatile void*     dest) { (void)add_ptr(-1, dest); }
    56 #ifdef _LP64
    58 inline void Atomic::store(jlong store_value, jlong* dest) { *dest = store_value; }
    59 inline void Atomic::store(jlong store_value, volatile jlong* dest) { *dest = store_value; }
    60 inline jlong Atomic::load(volatile jlong* src) { return *src; }
    62 #else
    64 extern "C" void _Atomic_move_long_v8(volatile jlong* src, volatile jlong* dst);
    65 extern "C" void _Atomic_move_long_v9(volatile jlong* src, volatile jlong* dst);
    67 inline void Atomic_move_long(volatile jlong* src, volatile jlong* dst) {
    68 #ifdef COMPILER2
    69   // Compiler2 does not support v8, it is used only for v9.
    70   _Atomic_move_long_v9(src, dst);
    71 #else
    72   // The branch is cheaper then emulated LDD.
    73   if (VM_Version::v9_instructions_work()) {
    74     _Atomic_move_long_v9(src, dst);
    75   } else {
    76     _Atomic_move_long_v8(src, dst);
    77   }
    78 #endif
    79 }
    81 inline jlong Atomic::load(volatile jlong* src) {
    82   volatile jlong dest;
    83   Atomic_move_long(src, &dest);
    84   return dest;
    85 }
    87 inline void Atomic::store(jlong store_value, jlong* dest) {
    88   Atomic_move_long((volatile jlong*)&store_value, (volatile jlong*)dest);
    89 }
    91 inline void Atomic::store(jlong store_value, volatile jlong* dest) {
    92   Atomic_move_long((volatile jlong*)&store_value, dest);
    93 }
    95 #endif
    97 #ifdef _GNU_SOURCE
    99 inline jint     Atomic::add    (jint     add_value, volatile jint*     dest) {
   100   intptr_t rv;
   101   __asm__ volatile(
   102     "1: \n\t"
   103     " ld     [%2], %%o2\n\t"
   104     " add    %1, %%o2, %%o3\n\t"
   105     " cas    [%2], %%o2, %%o3\n\t"
   106     " cmp    %%o2, %%o3\n\t"
   107     " bne    1b\n\t"
   108     "  nop\n\t"
   109     " add    %1, %%o2, %0\n\t"
   110     : "=r" (rv)
   111     : "r" (add_value), "r" (dest)
   112     : "memory", "o2", "o3");
   113   return rv;
   114 }
   116 inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) {
   117   intptr_t rv;
   118 #ifdef _LP64
   119   __asm__ volatile(
   120     "1: \n\t"
   121     " ldx    [%2], %%o2\n\t"
   122     " add    %0, %%o2, %%o3\n\t"
   123     " casx   [%2], %%o2, %%o3\n\t"
   124     " cmp    %%o2, %%o3\n\t"
   125     " bne    %%xcc, 1b\n\t"
   126     "  nop\n\t"
   127     " add    %0, %%o2, %0\n\t"
   128     : "=r" (rv)
   129     : "r" (add_value), "r" (dest)
   130     : "memory", "o2", "o3");
   131 #else //_LP64
   132   __asm__ volatile(
   133     "1: \n\t"
   134     " ld     [%2], %%o2\n\t"
   135     " add    %1, %%o2, %%o3\n\t"
   136     " cas    [%2], %%o2, %%o3\n\t"
   137     " cmp    %%o2, %%o3\n\t"
   138     " bne    1b\n\t"
   139     "  nop\n\t"
   140     " add    %1, %%o2, %0\n\t"
   141     : "=r" (rv)
   142     : "r" (add_value), "r" (dest)
   143     : "memory", "o2", "o3");
   144 #endif // _LP64
   145   return rv;
   146 }
   148 inline void*    Atomic::add_ptr(intptr_t add_value, volatile void*     dest) {
   149   return (void*)add_ptr((intptr_t)add_value, (volatile intptr_t*)dest);
   150 }
   153 inline jint     Atomic::xchg    (jint     exchange_value, volatile jint*     dest) {
   154   intptr_t rv = exchange_value;
   155   __asm__ volatile(
   156     " swap   [%2],%1\n\t"
   157     : "=r" (rv)
   158     : "0" (exchange_value) /* we use same register as for return value */, "r" (dest)
   159     : "memory");
   160   return rv;
   161 }
   163 inline intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest) {
   164   intptr_t rv = exchange_value;
   165 #ifdef _LP64
   166   __asm__ volatile(
   167     "1:\n\t"
   168     " mov    %1, %%o3\n\t"
   169     " ldx    [%2], %%o2\n\t"
   170     " casx   [%2], %%o2, %%o3\n\t"
   171     " cmp    %%o2, %%o3\n\t"
   172     " bne    %%xcc, 1b\n\t"
   173     "  nop\n\t"
   174     " mov    %%o2, %0\n\t"
   175     : "=r" (rv)
   176     : "r" (exchange_value), "r" (dest)
   177     : "memory", "o2", "o3");
   178 #else  //_LP64
   179   __asm__ volatile(
   180     "swap    [%2],%1\n\t"
   181     : "=r" (rv)
   182     : "0" (exchange_value) /* we use same register as for return value */, "r" (dest)
   183     : "memory");
   184 #endif // _LP64
   185   return rv;
   186 }
   188 inline void*    Atomic::xchg_ptr(void*    exchange_value, volatile void*     dest) {
   189   return (void*)xchg_ptr((intptr_t)exchange_value, (volatile intptr_t*)dest);
   190 }
   193 inline jint     Atomic::cmpxchg    (jint     exchange_value, volatile jint*     dest, jint     compare_value) {
   194   jint rv;
   195   __asm__ volatile(
   196     " cas    [%2], %3, %0"
   197     : "=r" (rv)
   198     : "0" (exchange_value), "r" (dest), "r" (compare_value)
   199     : "memory");
   200   return rv;
   201 }
   203 inline jlong    Atomic::cmpxchg    (jlong    exchange_value, volatile jlong*    dest, jlong    compare_value) {
   204 #ifdef _LP64
   205   jlong rv;
   206   __asm__ volatile(
   207     " casx   [%2], %3, %0"
   208     : "=r" (rv)
   209     : "0" (exchange_value), "r" (dest), "r" (compare_value)
   210     : "memory");
   211   return rv;
   212 #else  //_LP64
   213   assert(VM_Version::v9_instructions_work(), "cas only supported on v9");
   214   volatile jlong_accessor evl, cvl, rv;
   215   evl.long_value = exchange_value;
   216   cvl.long_value = compare_value;
   218   __asm__ volatile(
   219     " sllx   %2, 32, %2\n\t"
   220     " srl    %3, 0,  %3\n\t"
   221     " or     %2, %3, %2\n\t"
   222     " sllx   %5, 32, %5\n\t"
   223     " srl    %6, 0,  %6\n\t"
   224     " or     %5, %6, %5\n\t"
   225     " casx   [%4], %5, %2\n\t"
   226     " srl    %2, 0, %1\n\t"
   227     " srlx   %2, 32, %0\n\t"
   228     : "=r" (rv.words[0]), "=r" (rv.words[1])
   229     : "r"  (evl.words[0]), "r" (evl.words[1]), "r" (dest), "r" (cvl.words[0]), "r" (cvl.words[1])
   230     : "memory");
   232   return rv.long_value;
   233 #endif  //_LP64
   234 }
   236 inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value) {
   237   intptr_t rv;
   238 #ifdef _LP64
   239   __asm__ volatile(
   240     " casx    [%2], %3, %0"
   241     : "=r" (rv)
   242     : "0" (exchange_value), "r" (dest), "r" (compare_value)
   243     : "memory");
   244 #else  //_LP64
   245   __asm__ volatile(
   246     " cas     [%2], %3, %0"
   247     : "=r" (rv)
   248     : "0" (exchange_value), "r" (dest), "r" (compare_value)
   249     : "memory");
   250 #endif // _LP64
   251   return rv;
   252 }
   254 inline void*    Atomic::cmpxchg_ptr(void*    exchange_value, volatile void*     dest, void*    compare_value) {
   255   return (void*)cmpxchg_ptr((intptr_t)exchange_value, (volatile intptr_t*)dest, (intptr_t)compare_value);
   256 }
   258 #else // _GNU_SOURCE
   260 #if defined(COMPILER2) || defined(_LP64)
   262 // This is the interface to the atomic instructions in solaris_sparc.il.
   263 // It's very messy because we need to support v8 and these instructions
   264 // are illegal there.  When sparc v8 is dropped, we can drop out lots of
   265 // this code.  Also compiler2 does not support v8 so the conditional code
   266 // omits the instruction set check.
   268 extern "C" jint     _Atomic_swap32(jint     exchange_value, volatile jint*     dest);
   269 extern "C" intptr_t _Atomic_swap64(intptr_t exchange_value, volatile intptr_t* dest);
   271 extern "C" jint     _Atomic_cas32(jint     exchange_value, volatile jint*     dest, jint     compare_value);
   272 extern "C" intptr_t _Atomic_cas64(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value);
   273 extern "C" jlong    _Atomic_casl (jlong    exchange_value, volatile jlong*    dest, jlong    compare_value);
   275 extern "C" jint     _Atomic_add32(jint     inc,       volatile jint*     dest);
   276 extern "C" intptr_t _Atomic_add64(intptr_t add_value, volatile intptr_t* dest);
   279 inline jint     Atomic::add     (jint    add_value, volatile jint*     dest) {
   280   return _Atomic_add32(add_value, dest);
   281 }
   283 inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) {
   284 #ifdef _LP64
   285   return _Atomic_add64(add_value, dest);
   286 #else  //_LP64
   287   return _Atomic_add32(add_value, dest);
   288 #endif // _LP64
   289 }
   291 inline void*    Atomic::add_ptr(intptr_t add_value, volatile void*     dest) {
   292   return (void*)add_ptr((intptr_t)add_value, (volatile intptr_t*)dest);
   293 }
   296 inline jint     Atomic::xchg    (jint     exchange_value, volatile jint*     dest) {
   297   return _Atomic_swap32(exchange_value, dest);
   298 }
   300 inline intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest) {
   301 #ifdef _LP64
   302   return _Atomic_swap64(exchange_value, dest);
   303 #else  // _LP64
   304   return _Atomic_swap32(exchange_value, dest);
   305 #endif // _LP64
   306 }
   308 inline void*    Atomic::xchg_ptr(void*    exchange_value, volatile void*     dest) {
   309   return (void*)xchg_ptr((intptr_t)exchange_value, (volatile intptr_t*)dest);
   310 }
   313 inline jint     Atomic::cmpxchg    (jint     exchange_value, volatile jint*     dest, jint     compare_value) {
   314   return _Atomic_cas32(exchange_value, dest, compare_value);
   315 }
   317 inline jlong    Atomic::cmpxchg    (jlong    exchange_value, volatile jlong*    dest, jlong    compare_value) {
   318 #ifdef _LP64
   319   // Return 64 bit value in %o0
   320   return _Atomic_cas64((intptr_t)exchange_value, (intptr_t *)dest, (intptr_t)compare_value);
   321 #else  // _LP64
   322   assert (VM_Version::v9_instructions_work(), "only supported on v9");
   323   // Return 64 bit value in %o0,%o1 by hand
   324   return _Atomic_casl(exchange_value, dest, compare_value);
   325 #endif // _LP64
   326 }
   328 inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value) {
   329 #ifdef _LP64
   330   return _Atomic_cas64(exchange_value, dest, compare_value);
   331 #else  // _LP64
   332   return _Atomic_cas32(exchange_value, dest, compare_value);
   333 #endif // _LP64
   334 }
   336 inline void*    Atomic::cmpxchg_ptr(void*    exchange_value, volatile void*     dest, void*    compare_value) {
   337   return (void*)cmpxchg_ptr((intptr_t)exchange_value, (volatile intptr_t*)dest, (intptr_t)compare_value);
   338 }
   341 #else // _LP64 || COMPILER2
   344 // 32-bit compiler1 only
   346 inline jint     Atomic::add    (jint     add_value, volatile jint*     dest) {
   347   return (*os::atomic_add_func)(add_value, dest);
   348 }
   350 inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) {
   351   return (intptr_t)add((jint)add_value, (volatile jint*)dest);
   352 }
   354 inline void*    Atomic::add_ptr(intptr_t add_value, volatile void*     dest) {
   355   return (void*)add((jint)add_value, (volatile jint*)dest);
   356 }
   359 inline jint     Atomic::xchg    (jint     exchange_value, volatile jint*     dest) {
   360   return (*os::atomic_xchg_func)(exchange_value, dest);
   361 }
   363 inline intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest) {
   364   return (intptr_t)xchg((jint)exchange_value, (volatile jint*)dest);
   365 }
   367 inline void*    Atomic::xchg_ptr(void*    exchange_value, volatile void*     dest) {
   368   return (void*)xchg((jint)exchange_value, (volatile jint*)dest);
   369 }
   372 inline jint     Atomic::cmpxchg    (jint     exchange_value, volatile jint*     dest, jint     compare_value) {
   373   return (*os::atomic_cmpxchg_func)(exchange_value, dest, compare_value);
   374 }
   376 inline jlong    Atomic::cmpxchg    (jlong    exchange_value, volatile jlong*    dest, jlong    compare_value) {
   377   return (*os::atomic_cmpxchg_long_func)(exchange_value, dest, compare_value);
   378 }
   380 inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value) {
   381   return (intptr_t)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value);
   382 }
   384 inline void*    Atomic::cmpxchg_ptr(void*    exchange_value, volatile void*     dest, void*    compare_value) {
   385   return (void*)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value);
   386 }
   388 #endif // _LP64 || COMPILER2
   390 #endif // _GNU_SOURCE
   392 #endif // OS_CPU_SOLARIS_SPARC_VM_ATOMIC_SOLARIS_SPARC_INLINE_HPP

mercurial