
Hi Markus, Thank you for continuing to support Boost on Tru64. I've asked Rich Peterson to review your implementation. I don't know yet when (and if) Rich will be able to do it. I think #elif defined(__osf__) should be: #elif defined(__osf__) && defined(__DECCXX) to not break compilation with gcc. I'm a bit surprised you did not use __ATOMIC_EXCH_LONG in atomic_write32(). I'm also not sure why you decided to implement atomic_cas32() in asm language instead of using __CMP_STORE_LONG: /* ** Compare, Store Longword/Quadword ** If *source matches old_value, store new_value in *dest, returning ** 0 if no match or if compare and store were not interlocked. ** NOTE: Memory Barrier only within the LDx_L/STx_C sequence. */ int __CMP_STORE_LONG(volatile void *__source, int __old_value, int __new_value, volatile void *__dest); For atomic_cas32(), __source and __dest would be the same. See /usr/lib/cmplrs/cxx/V7.1-006/include/cxx/string_ref for how we use atomic builtins in RW library. Anyway, Rich is an expert in this stuff and, hopefully, he will be able to review your implementation. Thanks, Boris ----- Original Message ----- From: "Markus Schöpflin" <markus.schoepflin@comsoft.de> To: <boost@lists.boost.org> Sent: Thursday, October 18, 2007 10:35 AM Subject: [boost] [interprocess] Atomic ops supports for Alpha processors.
Hello,
attached patch introduces support for the atomic ops needed by interprocess on Tru64/CXX/Alpha. It currently misses support for atomic add and sub, but those are not used right now.
There are a few issues I would like to raise regarding the atomic operations:
1) Currently it is not specified whether an atomic operation implies a memory barrier or not. This should be explicitly stated.
2) atomic_sub32 does not return the old value, but atomic_add32 does. This seems inconsistent to me.
3) Has the use of the low level atomic ops API as proposed in WG21/N2047 (see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2047.html) been considered. If yes, why has it been rejected? If no, would it makes sense to use this API?
4) Is there a need for an atomic ops boost library? I seem to remember that other libraries need atomic ops as well.
Regards, Markus
--------------------------------------------------------------------------------
Index: atomic.hpp =================================================================== --- atomic.hpp (revision 40078) +++ atomic.hpp (working copy) @@ -436,6 +436,82 @@ } //namespace interprocess{ } //namespace boost{
+#elif defined(__osf__) + +#include <machine/builtins.h> +#include <c_asm.h> + +namespace boost{ +namespace interprocess{ +namespace detail{ + +//! Atomically increment an apr_uint32_t by 1 +//! "mem": pointer to the object +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem) +{ return __ATOMIC_INCREMENT_LONG(mem); } + +//! Atomically decrement an boost::uint32_t by 1 +//! "mem": pointer to the atomic value +//! Returns false if the value becomes zero on decrement, otherwise true +inline bool atomic_dec32(volatile boost::uint32_t *mem) +{ return __ATOMIC_DECREMENT_LONG(mem); } + +// Rational for the implementation of the atomic read and write functions. +// +// 1. The Alpha Architecture Handbook requires that access to a byte, +// an aligned word, an aligned longword, or an aligned quadword is +// atomic. (See 'Alpha Architecture Handbook', version 4, chapter 5.2.2.) +// +// 2. The CXX User's Guide states that volatile quantities are accessed +// with single assembler instructions, and that a compilation error +// occurs when declaring a quantity as volatile which is not properly +// aligned. + +//! Atomically read an boost::uint32_t from memory +inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) +{ return *mem; } + +//! Atomically set an boost::uint32_t in memory +//! "mem": pointer to the object +//! "param": val value that the object will assume +inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val) +{ *mem = val; } + +//! Compare an boost::uint32_t's value with "cmp". +//! If they are the same swap the value with "with" +//! "mem": pointer to the value +//! "with" what to swap it with +//! "cmp": the value to compare it to +//! Returns the old value of *mem +inline boost::uint32_t atomic_cas32 + (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp) +{ + // Notes: + // + // 1. Branch prediction prefers branches, as we assume that the lock + // is not stolen usually, we branch forward conditionally on success + // of the store, and not conditionally backwards on failure. + // + // 2. The memory lock is invalidated when a branch is taken between + // load and store. Therefore we can only branch if we don't need a + // store. + + return asm("10: ldl_l %v0,(%a0) ;" // load prev value from mem and lock mem + " cmpeq %v0,%a2,%t0 ;" // compare with given value + " beq %t0,20f ;" // if not equal, we're done + " mov %a1,%t0 ;" // load new value into scratch register + " stl_c %t0,(%a0) ;" // store new value to locked mem (overwriting scratch) + " bne %t0,20f ;" // store succeeded, we're done + " br 10b ;" // lock has been stolen, retry + "20: ", + mem, with, cmp); +} + +} //namespace detail{ +} //namespace interprocess{ +} //namespace boost{ + #else
#error No atomic operations implemented for this platform, sorry!
--------------------------------------------------------------------------------
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost