Boost logo

Boost :

From: Markus Schöpflin (markus.schoepflin_at_[hidden])
Date: 2007-10-18 10:35:26


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
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.


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{
 #error No atomic operations implemented for this platform, sorry!

Boost list run by bdawes at, gregod at, cpdaniel at, john at