/* * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2019 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. *
*/
// // machine barrier instructions: // // - sync two-way memory barrier, aka fence // - lwsync orders Store|Store, // Load|Store, // Load|Load, // but not Store|Load // - eieio orders memory accesses for device memory (only) // - isync invalidates speculatively executed instructions // From the POWER ISA 2.06 documentation: // "[...] an isync instruction prevents the execution of // instructions following the isync until instructions // preceding the isync have completed, [...]" // From IBM's AIX assembler reference: // "The isync [...] instructions causes the processor to // refetch any instructions that might have been fetched // prior to the isync instruction. The instruction isync // causes the processor to wait for all previous instructions // to complete. Then any instructions already fetched are // discarded and instruction processing continues in the // environment established by the previous instructions." // // semantic barrier instructions: // (as defined in orderAccess.hpp) // // - release orders Store|Store, (maps to lwsync) // Load|Store // - acquire orders Load|Store, (maps to lwsync) // Load|Load // - fence orders Store|Store, (maps to sync) // Load|Store, // Load|Load, // Store|Load //
inlinevoid pre_membar(atomic_memory_order order) { switch (order) { case memory_order_relaxed: case memory_order_acquire: break; case memory_order_release: case memory_order_acq_rel: __asm__ __volatile__ ("lwsync" : : : "memory"); break; default/*conservative*/ : __asm__ __volatile__ ("sync" : : : "memory"); break;
}
}
inlinevoid post_membar(atomic_memory_order order) { switch (order) { case memory_order_relaxed: case memory_order_release: break; case memory_order_acquire: case memory_order_acq_rel: __asm__ __volatile__ ("isync" : : : "memory"); break; default/*conservative*/ : __asm__ __volatile__ ("sync" : : : "memory"); break;
}
}
template<size_t byte_size> struct Atomic::PlatformAdd { template<typename D, typename I>
D add_and_fetch(D volatile* dest, I add_value, atomic_memory_order order) const;
template<> template<typename T> inline T Atomic::PlatformXchg<4>::operator()(T volatile* dest,
T exchange_value,
atomic_memory_order order) const { // Note that xchg doesn't necessarily do an acquire // (see synchronizer.cpp).
template<> template<typename T> inline T Atomic::PlatformXchg<8>::operator()(T volatile* dest,
T exchange_value,
atomic_memory_order order) const {
STATIC_ASSERT(8 == sizeof(T)); // Note that xchg doesn't necessarily do an acquire // (see synchronizer.cpp).
template<> template<typename T> inline T Atomic::PlatformCmpxchg<1>::operator()(T volatile* dest,
T compare_value,
T exchange_value,
atomic_memory_order order) const {
STATIC_ASSERT(1 == sizeof(T));
// Note that cmpxchg guarantees a two-way memory barrier across // the cmpxchg, so it's really a 'fence_cmpxchg_fence' if not // specified otherwise (see atomic.hpp).
// Using 32 bit internally. volatileint *dest_base = (volatileint*)((uintptr_t)dest & ~3);
template<> template<typename T> inline T Atomic::PlatformCmpxchg<4>::operator()(T volatile* dest,
T compare_value,
T exchange_value,
atomic_memory_order order) const {
STATIC_ASSERT(4 == sizeof(T));
// Note that cmpxchg guarantees a two-way memory barrier across // the cmpxchg, so it's really a 'fence_cmpxchg_fence' if not // specified otherwise (see atomic.hpp).
template<> template<typename T> inline T Atomic::PlatformCmpxchg<8>::operator()(T volatile* dest,
T compare_value,
T exchange_value,
atomic_memory_order order) const {
STATIC_ASSERT(8 == sizeof(T));
// Note that cmpxchg guarantees a two-way memory barrier across // the cmpxchg, so it's really a 'fence_cmpxchg_fence' if not // specified otherwise (see atomic.hpp).
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.