diff options
Diffstat (limited to 'boost/interprocess/detail/atomic.hpp')
-rw-r--r-- | boost/interprocess/detail/atomic.hpp | 355 |
1 files changed, 162 insertions, 193 deletions
diff --git a/boost/interprocess/detail/atomic.hpp b/boost/interprocess/detail/atomic.hpp index f7551f3dda..aab1533985 100644 --- a/boost/interprocess/detail/atomic.hpp +++ b/boost/interprocess/detail/atomic.hpp @@ -117,23 +117,6 @@ inline boost::uint32_t atomic_cas32 : "cc"); return prev; -/* - asm volatile( "lock\n\t" - "cmpxchg %3,%1" - : "=a" (prev), "=m" (*(mem)) - : "0" (prev), "r" (with) - : "memory", "cc"); -*/ -/* - boost::uint32_t prev; - - asm volatile ("lock; cmpxchgl %1, %2" - : "=a" (prev) - : "r" (with), "m" (*(mem)), "0"(cmp)); - asm volatile("" : : : "memory"); - - return prev; -*/ } //! Atomically add 'val' to an boost::uint32_t @@ -158,14 +141,6 @@ inline boost::uint32_t atomic_add32 ); return r; -/* - asm volatile( "lock\n\t; xaddl %0,%1" - : "=r"(val), "=m"(*mem) - : "0"(val), "m"(*mem)); - asm volatile("" : : : "memory"); - - return val; -*/ } //! Atomically increment an apr_uint32_t by 1 @@ -208,17 +183,14 @@ inline boost::uint32_t atomic_add32(volatile boost::uint32_t *mem, boost::uint32 { boost::uint32_t prev, temp; - asm volatile ("0:\n\t" // retry local label - "lwarx %0,0,%2\n\t" // load prev and reserve - "add %1,%0,%3\n\t" // temp = prev + val - "stwcx. %1,0,%2\n\t" // conditionally store - "bne- 0b" // start over if we lost - // the reservation - //XXX find a cleaner way to define the temp - //it's not an output - : "=&r" (prev), "=&r" (temp) // output, temp - : "b" (mem), "r" (val) // inputs - : "memory", "cc"); // clobbered + asm volatile ("1:\n\t" + "lwarx %0,0,%2\n\t" + "add %1,%0,%3\n\t" + "stwcx. %1,0,%2\n\t" + "bne- 1b" + : "=&r" (prev), "=&r" (temp) + : "b" (mem), "r" (val) + : "cc", "memory"); return prev; } @@ -233,19 +205,16 @@ inline boost::uint32_t atomic_cas32 { boost::uint32_t prev; - asm volatile ("0:\n\t" // retry local label - "lwarx %0,0,%1\n\t" // load prev and reserve - "cmpw %0,%3\n\t" // does it match cmp? - "bne- 1f\n\t" // ...no, bail out - "stwcx. %2,0,%1\n\t" // ...yes, conditionally - // store with - "bne- 0b\n\t" // start over if we lost - // the reservation - "1:" // exit local label - - : "=&r"(prev) // output - : "b" (mem), "r" (with), "r"(cmp) // inputs - : "memory", "cc"); // clobbered + asm volatile ("1:\n\t" + "lwarx %0,0,%1\n\t" + "cmpw %0,%3\n\t" + "bne- 2f\n\t" + "stwcx. %2,0,%1\n\t" + "bne- 1b\n\t" + "2:" + : "=&r"(prev) + : "b" (mem), "r"(cmp), "r" (with) + : "cc", "memory"); return prev; } @@ -275,56 +244,6 @@ inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val) } //namespace interprocess{ } //namespace boost{ -#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) - -namespace boost { -namespace interprocess { -namespace ipcdetail{ - -//! Atomically add 'val' to an boost::uint32_t -//! "mem": pointer to the object -//! "val": amount to add -//! Returns the old value pointed to by mem -inline boost::uint32_t atomic_add32 - (volatile boost::uint32_t *mem, boost::uint32_t val) -{ return __sync_fetch_and_add(const_cast<boost::uint32_t *>(mem), val); } - -//! 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_add32(mem, 1); } - -//! Atomically decrement an boost::uint32_t by 1 -//! "mem": pointer to the atomic value -//! Returns the old value pointed to by mem -inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem) -{ return atomic_add32(mem, (boost::uint32_t)-1); } - -//! Atomically read an boost::uint32_t from memory -inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) -{ return *mem; } - -//! 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) -{ return __sync_val_compare_and_swap(const_cast<boost::uint32_t *>(mem), cmp, with); } - -//! 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; } - -} //namespace ipcdetail{ -} //namespace interprocess{ -} //namespace boost{ - #elif (defined(sun) || defined(__sun)) #include <atomic.h> @@ -471,97 +390,147 @@ inline boost::uint32_t atomic_cas32( } //namespace interprocess{ } //namespace boost{ -#elif defined(__IBMCPP__) && (__IBMCPP__ >= 800) && defined(_AIX) - -#include <builtins.h> - -namespace boost { -namespace interprocess { -namespace ipcdetail{ - -//first define boost::uint32_t versions of __lwarx and __stwcx to avoid poluting -//all the functions with casts - -//! From XLC documenation : -//! This function can be used with a subsequent stwcxu call to implement a -//! read-modify-write on a specified memory location. The two functions work -//! together to ensure that if the store is successfully performed, no other -//! processor or mechanism can modify the target doubleword between the time -//! lwarxu function is executed and the time the stwcxu functio ncompletes. -//! "mem" : pointer to the object -//! Returns the value at pointed to by mem -inline boost::uint32_t lwarxu(volatile boost::uint32_t *mem) -{ - return static_cast<boost::uint32_t>(__lwarx(reinterpret_cast<volatile int*>(mem))); -} - -//! "mem" : pointer to the object -//! "val" : the value to store -//! Returns true if the update of mem is successful and false if it is -//!unsuccessful -inline bool stwcxu(volatile boost::uint32_t* mem, boost::uint32_t val) -{ - return (__stwcx(reinterpret_cast<volatile int*>(mem), static_cast<int>(val)) != 0); -} - -//! "mem": pointer to the object -//! "val": amount to add -//! Returns the old value pointed to by mem -inline boost::uint32_t atomic_add32 - (volatile boost::uint32_t *mem, boost::uint32_t val) -{ - boost::uint32_t oldValue; - do - { - oldValue = lwarxu(mem); - }while (!stwcxu(mem, oldValue+val)); - return oldValue; -} - -//! 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_add32(mem, 1); } - -//! Atomically decrement an boost::uint32_t by 1 -//! "mem": pointer to the atomic value -//! Returns the old value pointed to by mem -inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem) -{ return atomic_add32(mem, (boost::uint32_t)-1); } - -//! Atomically read an boost::uint32_t from memory -inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) -{ return *mem; } - -//! 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) -{ - boost::uint32_t oldValue; - boost::uint32_t valueToStore; - do - { - oldValue = lwarxu(mem); - } while (!stwcxu(mem, (oldValue == with) ? cmp : oldValue)); - - return oldValue; -} - -//! 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; } - -} //namespace ipcdetail -} //namespace interprocess -} //namespace boost +#elif defined(__IBMCPP__) && (__IBMCPP__ >= 800) && defined(_AIX) + +#include <builtins.h> + +namespace boost { +namespace interprocess { +namespace ipcdetail{ + +//first define boost::uint32_t versions of __lwarx and __stwcx to avoid poluting +//all the functions with casts + +//! From XLC documenation : +//! This function can be used with a subsequent stwcxu call to implement a +//! read-modify-write on a specified memory location. The two functions work +//! together to ensure that if the store is successfully performed, no other +//! processor or mechanism can modify the target doubleword between the time +//! lwarxu function is executed and the time the stwcxu functio ncompletes. +//! "mem" : pointer to the object +//! Returns the value at pointed to by mem +inline boost::uint32_t lwarxu(volatile boost::uint32_t *mem) +{ + return static_cast<boost::uint32_t>(__lwarx(reinterpret_cast<volatile int*>(mem))); +} + +//! "mem" : pointer to the object +//! "val" : the value to store +//! Returns true if the update of mem is successful and false if it is +//!unsuccessful +inline bool stwcxu(volatile boost::uint32_t* mem, boost::uint32_t val) +{ + return (__stwcx(reinterpret_cast<volatile int*>(mem), static_cast<int>(val)) != 0); +} + +//! "mem": pointer to the object +//! "val": amount to add +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_add32 + (volatile boost::uint32_t *mem, boost::uint32_t val) +{ + boost::uint32_t oldValue; + do + { + oldValue = lwarxu(mem); + }while (!stwcxu(mem, oldValue+val)); + return oldValue; +} + +//! 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_add32(mem, 1); } + +//! Atomically decrement an boost::uint32_t by 1 +//! "mem": pointer to the atomic value +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem) +{ return atomic_add32(mem, (boost::uint32_t)-1); } + +//! Atomically read an boost::uint32_t from memory +inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) +{ return *mem; } + +//! 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) +{ + boost::uint32_t oldValue; + boost::uint32_t valueToStore; + do + { + oldValue = lwarxu(mem); + } while (!stwcxu(mem, (oldValue == with) ? cmp : oldValue)); + + return oldValue; +} + +//! 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; } + +} //namespace ipcdetail +} //namespace interprocess +} //namespace boost + +#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) + +namespace boost { +namespace interprocess { +namespace ipcdetail{ + +//! Atomically add 'val' to an boost::uint32_t +//! "mem": pointer to the object +//! "val": amount to add +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_add32 + (volatile boost::uint32_t *mem, boost::uint32_t val) +{ return __sync_fetch_and_add(const_cast<boost::uint32_t *>(mem), val); } + +//! 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_add32(mem, 1); } + +//! Atomically decrement an boost::uint32_t by 1 +//! "mem": pointer to the atomic value +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem) +{ return atomic_add32(mem, (boost::uint32_t)-1); } + +//! Atomically read an boost::uint32_t from memory +inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) +{ return *mem; } + +//! 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) +{ return __sync_val_compare_and_swap(const_cast<boost::uint32_t *>(mem), cmp, with); } + +//! 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; } + +} //namespace ipcdetail{ +} //namespace interprocess{ +} //namespace boost{ #else @@ -583,9 +552,9 @@ inline bool atomic_add_unless32 return c != unless_this; } -} //namespace ipcdetail -} //namespace interprocess -} //namespace boost +} //namespace ipcdetail +} //namespace interprocess +} //namespace boost #include <boost/interprocess/detail/config_end.hpp> |