|
Boost : |
From: Boris Gubenko (Boris.Gubenko_at_[hidden])
Date: 2007-10-18 14:25:24
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_at_[hidden]>
To: <boost_at_[hidden]>
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
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk