53 54 // The memory operations that are mentioned with each of the atomic 55 // function families come from src/share/vm/runtime/orderAccess.hpp, 56 // e.g., <fence> is described in that file and is implemented by the 57 // OrderAccess::fence() function. See that file for the gory details 58 // on the Memory Access Ordering Model. 59 60 // All of the atomic operations that imply a read-modify-write action 61 // guarantee a two-way memory barrier across that operation. Historically 62 // these semantics reflect the strength of atomic operations that are 63 // provided on SPARC/X86. We assume that strength is necessary unless 64 // we can prove that a weaker form is sufficiently safe. 65 66 // Atomically store to a location 67 // The type T must be either a pointer type convertible to or equal 68 // to D, an integral/enum type equal to D, or a type equal to D that 69 // is primitive convertible using PrimitiveConversions. 70 template<typename T, typename D> 71 inline static void store(T store_value, volatile D* dest); 72 73 inline static void store_ptr(intptr_t store_value, volatile intptr_t* dest) { 74 Atomic::store(store_value, dest); 75 } 76 77 inline static void store_ptr(void* store_value, volatile void* dest) { 78 Atomic::store(store_value, reinterpret_cast<void* volatile*>(dest)); 79 } 80 81 // Atomically load from a location 82 // The type T must be either a pointer type, an integral/enum type, 83 // or a type that is primitive convertible using PrimitiveConversions. 84 template<typename T> 85 inline static T load(const volatile T* dest); 86 87 // Atomically add to a location. Returns updated value. add*() provide: 88 // <fence> add-value-to-dest <membar StoreLoad|StoreStore> 89 90 template<typename I, typename D> 91 inline static D add(I add_value, D volatile* dest); 92 93 inline static intptr_t add_ptr(intptr_t add_value, volatile intptr_t* dest) { 94 return add(add_value, dest); 95 } 96 97 inline static void* add_ptr(intptr_t add_value, volatile void* dest) { 98 return add(add_value, reinterpret_cast<char* volatile*>(dest)); 99 } 100 101 // Atomically increment location. inc() provide: 102 // <fence> increment-dest <membar StoreLoad|StoreStore> 103 // The type D may be either a pointer type, or an integral 104 // type. If it is a pointer type, then the increment is 105 // scaled to the size of the type pointed to by the pointer. 106 template<typename D> 107 inline static void inc(D volatile* dest); 108 109 // Atomically decrement a location. dec() provide: 110 // <fence> decrement-dest <membar StoreLoad|StoreStore> 111 // The type D may be either a pointer type, or an integral 112 // type. If it is a pointer type, then the decrement is 113 // scaled to the size of the type pointed to by the pointer. 114 template<typename D> 115 inline static void dec(D volatile* dest); 116 117 // Performs atomic exchange of *dest with exchange_value. Returns old 118 // prior value of *dest. xchg*() provide: 119 // <fence> exchange-value-with-dest <membar StoreLoad|StoreStore> 120 // The type T must be either a pointer type convertible to or equal 121 // to D, an integral/enum type equal to D, or a type equal to D that 122 // is primitive convertible using PrimitiveConversions. 123 template<typename T, typename D> 124 inline static D xchg(T exchange_value, volatile D* dest); 125 126 inline static intptr_t xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest) { 127 return xchg(exchange_value, dest); 128 } 129 130 inline static void* xchg_ptr(void* exchange_value, volatile void* dest) { 131 return xchg(exchange_value, reinterpret_cast<void* volatile*>(dest)); 132 } 133 134 // Performs atomic compare of *dest and compare_value, and exchanges 135 // *dest with exchange_value if the comparison succeeded. Returns prior 136 // value of *dest. cmpxchg*() provide: 137 // <fence> compare-and-exchange <membar StoreLoad|StoreStore> 138 139 template<typename T, typename D, typename U> 140 inline static D cmpxchg(T exchange_value, 141 D volatile* dest, 142 U compare_value, 143 cmpxchg_memory_order order = memory_order_conservative); 144 145 // Performs atomic compare of *dest and NULL, and replaces *dest 146 // with exchange_value if the comparison succeeded. Returns true if 147 // the comparison succeeded and the exchange occurred. This is 148 // often used as part of lazy initialization, as a lock-free 149 // alternative to the Double-Checked Locking Pattern. 150 template<typename T, typename D> 151 inline static bool replace_if_null(T* value, D* volatile* dest, 152 cmpxchg_memory_order order = memory_order_conservative); 153 154 inline static intptr_t cmpxchg_ptr(intptr_t exchange_value, 155 volatile intptr_t* dest, 156 intptr_t compare_value, 157 cmpxchg_memory_order order = memory_order_conservative) { 158 return cmpxchg(exchange_value, dest, compare_value, order); 159 } 160 161 inline static void* cmpxchg_ptr(void* exchange_value, 162 volatile void* dest, 163 void* compare_value, 164 cmpxchg_memory_order order = memory_order_conservative) { 165 return cmpxchg(exchange_value, 166 reinterpret_cast<void* volatile*>(dest), 167 compare_value, 168 order); 169 } 170 171 private: 172 // Test whether From is implicitly convertible to To. 173 // From and To must be pointer types. 174 // Note: Provides the limited subset of C++11 std::is_convertible 175 // that is needed here. 176 template<typename From, typename To> struct IsPointerConvertible; 177 178 protected: 179 // Dispatch handler for store. Provides type-based validity 180 // checking and limited conversions around calls to the platform- 181 // specific implementation layer provided by PlatformOp. 182 template<typename T, typename D, typename PlatformOp, typename Enable = void> 183 struct StoreImpl; 184 185 // Platform-specific implementation of store. Support for sizes 186 // of 1, 2, 4, and (if different) pointer size bytes are required. 187 // The class is a function object that must be default constructable, 188 // with these requirements: 189 // 190 // either: 536 template<typename Derived> 537 struct Atomic::AddAndFetch VALUE_OBJ_CLASS_SPEC { 538 template<typename I, typename D> 539 D operator()(I add_value, D volatile* dest) const; 540 }; 541 542 template<typename D> 543 inline void Atomic::inc(D volatile* dest) { 544 STATIC_ASSERT(IsPointer<D>::value || IsIntegral<D>::value); 545 typedef typename Conditional<IsPointer<D>::value, ptrdiff_t, D>::type I; 546 Atomic::add(I(1), dest); 547 } 548 549 template<typename D> 550 inline void Atomic::dec(D volatile* dest) { 551 STATIC_ASSERT(IsPointer<D>::value || IsIntegral<D>::value); 552 typedef typename Conditional<IsPointer<D>::value, ptrdiff_t, D>::type I; 553 // Assumes two's complement integer representation. 554 #pragma warning(suppress: 4146) 555 Atomic::add(I(-1), dest); 556 } 557 558 // Define the class before including platform file, which may specialize 559 // the operator definition. No generic definition of specializations 560 // of the operator template are provided, nor are there any generic 561 // specializations of the class. The platform file is responsible for 562 // providing those. 563 template<size_t byte_size> 564 struct Atomic::PlatformCmpxchg VALUE_OBJ_CLASS_SPEC { 565 template<typename T> 566 T operator()(T exchange_value, 567 T volatile* dest, 568 T compare_value, 569 cmpxchg_memory_order order) const; 570 }; 571 572 // Define the class before including platform file, which may use this 573 // as a base class, requiring it be complete. The definition is later 574 // in this file, near the other definitions related to cmpxchg. 575 struct Atomic::CmpxchgByteUsingInt VALUE_OBJ_CLASS_SPEC { | 53 54 // The memory operations that are mentioned with each of the atomic 55 // function families come from src/share/vm/runtime/orderAccess.hpp, 56 // e.g., <fence> is described in that file and is implemented by the 57 // OrderAccess::fence() function. See that file for the gory details 58 // on the Memory Access Ordering Model. 59 60 // All of the atomic operations that imply a read-modify-write action 61 // guarantee a two-way memory barrier across that operation. Historically 62 // these semantics reflect the strength of atomic operations that are 63 // provided on SPARC/X86. We assume that strength is necessary unless 64 // we can prove that a weaker form is sufficiently safe. 65 66 // Atomically store to a location 67 // The type T must be either a pointer type convertible to or equal 68 // to D, an integral/enum type equal to D, or a type equal to D that 69 // is primitive convertible using PrimitiveConversions. 70 template<typename T, typename D> 71 inline static void store(T store_value, volatile D* dest); 72 73 // Atomically load from a location 74 // The type T must be either a pointer type, an integral/enum type, 75 // or a type that is primitive convertible using PrimitiveConversions. 76 template<typename T> 77 inline static T load(const volatile T* dest); 78 79 // Atomically add to a location. Returns updated value. add*() provide: 80 // <fence> add-value-to-dest <membar StoreLoad|StoreStore> 81 82 template<typename I, typename D> 83 inline static D add(I add_value, D volatile* dest); 84 85 template<typename I, typename D> 86 inline static D sub(I sub_value, D volatile* dest); 87 88 // Atomically increment location. inc() provide: 89 // <fence> increment-dest <membar StoreLoad|StoreStore> 90 // The type D may be either a pointer type, or an integral 91 // type. If it is a pointer type, then the increment is 92 // scaled to the size of the type pointed to by the pointer. 93 template<typename D> 94 inline static void inc(D volatile* dest); 95 96 // Atomically decrement a location. dec() provide: 97 // <fence> decrement-dest <membar StoreLoad|StoreStore> 98 // The type D may be either a pointer type, or an integral 99 // type. If it is a pointer type, then the decrement is 100 // scaled to the size of the type pointed to by the pointer. 101 template<typename D> 102 inline static void dec(D volatile* dest); 103 104 // Performs atomic exchange of *dest with exchange_value. Returns old 105 // prior value of *dest. xchg*() provide: 106 // <fence> exchange-value-with-dest <membar StoreLoad|StoreStore> 107 // The type T must be either a pointer type convertible to or equal 108 // to D, an integral/enum type equal to D, or a type equal to D that 109 // is primitive convertible using PrimitiveConversions. 110 template<typename T, typename D> 111 inline static D xchg(T exchange_value, volatile D* dest); 112 113 // Performs atomic compare of *dest and compare_value, and exchanges 114 // *dest with exchange_value if the comparison succeeded. Returns prior 115 // value of *dest. cmpxchg*() provide: 116 // <fence> compare-and-exchange <membar StoreLoad|StoreStore> 117 118 template<typename T, typename D, typename U> 119 inline static D cmpxchg(T exchange_value, 120 D volatile* dest, 121 U compare_value, 122 cmpxchg_memory_order order = memory_order_conservative); 123 124 // Performs atomic compare of *dest and NULL, and replaces *dest 125 // with exchange_value if the comparison succeeded. Returns true if 126 // the comparison succeeded and the exchange occurred. This is 127 // often used as part of lazy initialization, as a lock-free 128 // alternative to the Double-Checked Locking Pattern. 129 template<typename T, typename D> 130 inline static bool replace_if_null(T* value, D* volatile* dest, 131 cmpxchg_memory_order order = memory_order_conservative); 132 133 private: 134 // Test whether From is implicitly convertible to To. 135 // From and To must be pointer types. 136 // Note: Provides the limited subset of C++11 std::is_convertible 137 // that is needed here. 138 template<typename From, typename To> struct IsPointerConvertible; 139 140 protected: 141 // Dispatch handler for store. Provides type-based validity 142 // checking and limited conversions around calls to the platform- 143 // specific implementation layer provided by PlatformOp. 144 template<typename T, typename D, typename PlatformOp, typename Enable = void> 145 struct StoreImpl; 146 147 // Platform-specific implementation of store. Support for sizes 148 // of 1, 2, 4, and (if different) pointer size bytes are required. 149 // The class is a function object that must be default constructable, 150 // with these requirements: 151 // 152 // either: 498 template<typename Derived> 499 struct Atomic::AddAndFetch VALUE_OBJ_CLASS_SPEC { 500 template<typename I, typename D> 501 D operator()(I add_value, D volatile* dest) const; 502 }; 503 504 template<typename D> 505 inline void Atomic::inc(D volatile* dest) { 506 STATIC_ASSERT(IsPointer<D>::value || IsIntegral<D>::value); 507 typedef typename Conditional<IsPointer<D>::value, ptrdiff_t, D>::type I; 508 Atomic::add(I(1), dest); 509 } 510 511 template<typename D> 512 inline void Atomic::dec(D volatile* dest) { 513 STATIC_ASSERT(IsPointer<D>::value || IsIntegral<D>::value); 514 typedef typename Conditional<IsPointer<D>::value, ptrdiff_t, D>::type I; 515 // Assumes two's complement integer representation. 516 #pragma warning(suppress: 4146) 517 Atomic::add(I(-1), dest); 518 } 519 520 template<typename I, typename D> 521 inline D Atomic::sub(I sub_value, D volatile* dest) { 522 STATIC_ASSERT(IsPointer<D>::value || IsIntegral<D>::value); 523 STATIC_ASSERT(IsIntegral<I>::value); 524 typedef typename Conditional<IsPointer<D>::value, ptrdiff_t, D>::type AddendType; 525 AddendType addend = sub_value; 526 STATIC_ASSERT((IsIntegral<D>::value && IsSigned<I>::value == IsSigned<AddendType>::value) || 527 IsPointer<D>::value); 528 // Assumes two's complement integer representation. 529 #pragma warning(suppress: 4146) 530 return Atomic::add(-addend, dest); 531 } 532 533 // Define the class before including platform file, which may specialize 534 // the operator definition. No generic definition of specializations 535 // of the operator template are provided, nor are there any generic 536 // specializations of the class. The platform file is responsible for 537 // providing those. 538 template<size_t byte_size> 539 struct Atomic::PlatformCmpxchg VALUE_OBJ_CLASS_SPEC { 540 template<typename T> 541 T operator()(T exchange_value, 542 T volatile* dest, 543 T compare_value, 544 cmpxchg_memory_order order) const; 545 }; 546 547 // Define the class before including platform file, which may use this 548 // as a base class, requiring it be complete. The definition is later 549 // in this file, near the other definitions related to cmpxchg. 550 struct Atomic::CmpxchgByteUsingInt VALUE_OBJ_CLASS_SPEC { |