Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-13 08:49:27

0001 //////////////////////////////////////////////////////////////////////////////
0002 //
0003 // (C) Copyright Ion Gaztanaga 2006-2012
0004 // (C) Copyright Markus Schoepflin 2007
0005 // (C) Copyright Bryce Lelbach 2010
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See
0008 // accompanying file LICENSE_1_0.txt or copy at
0009 // http://www.boost.org/LICENSE_1_0.txt)
0010 //
0011 // See http://www.boost.org/libs/interprocess for documentation.
0012 //
0013 //////////////////////////////////////////////////////////////////////////////
0014 
0015 #ifndef BOOST_INTERPROCESS_DETAIL_ATOMIC_HPP
0016 #define BOOST_INTERPROCESS_DETAIL_ATOMIC_HPP
0017 
0018 #ifndef BOOST_CONFIG_HPP
0019 #  include <boost/config.hpp>
0020 #endif
0021 0022 ">#
0023 #if defined(BOOST_HAS_PRAGMA_ONCE)
0024 #  pragma once
0025 #endif
0026 
0027 #include <boost/interprocess/detail/config_begin.hpp>
0028 #include <boost/interprocess/detail/workaround.hpp>
0029 #include <boost/cstdint.hpp>
0030 
0031 #if !defined(_AIX)
0032 #define BOOST_INTERPROCESS_DETAIL_PPC_ASM_LABEL(label) label ":\n\t"
0033 #define BOOST_INTERPROCESS_DETAIL_PPC_ASM_JUMP(insn, label, offset) insn " " label "\n\t"
0034 #else
0035 #define BOOST_INTERPROCESS_DETAIL_PPC_ASM_LABEL(label)
0036 #define BOOST_INTERPROCESS_DETAIL_PPC_ASM_JUMP(insn, label, offset) insn " $" offset "\n\t"
0037 #endif
0038 
0039 namespace boost{
0040 namespace interprocess{
0041 namespace ipcdetail{
0042 
0043 //! Atomically increment an boost::uint32_t by 1
0044 //! "mem": pointer to the object
0045 //! Returns the old value pointed to by mem
0046 inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem);
0047 
0048 //! Atomically read an boost::uint32_t from memory
0049 inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem);
0050 
0051 //! Atomically set an boost::uint32_t in memory
0052 //! "mem": pointer to the object
0053 //! "param": val value that the object will assume
0054 inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val);
0055 
0056 //! Compare an boost::uint32_t's value with "cmp".
0057 //! If they are the same swap the value with "with"
0058 //! "mem": pointer to the value
0059 //! "with": what to swap it with
0060 //! "cmp": the value to compare it to
0061 //! Returns the old value of *mem
0062 inline boost::uint32_t atomic_cas32
0063    (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp);
0064 
0065 }  //namespace ipcdetail{
0066 }  //namespace interprocess{
0067 }  //namespace boost{
0068 
0069 #if defined (BOOST_INTERPROCESS_WINDOWS)
0070 
0071 #include <boost/interprocess/detail/win32_api.hpp>
0072 
0073 #if defined( _MSC_VER )
0074    extern "C" void _ReadWriteBarrier(void);
0075    #pragma intrinsic(_ReadWriteBarrier)
0076 
0077 #define BOOST_INTERPROCESS_READ_WRITE_BARRIER \
0078             BOOST_INTERPROCESS_DISABLE_DEPRECATED_WARNING \
0079             _ReadWriteBarrier() \
0080             BOOST_INTERPROCESS_RESTORE_WARNING
0081 
0082 #elif defined(__GNUC__)
0083    #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
0084       #define BOOST_INTERPROCESS_READ_WRITE_BARRIER __sync_synchronize()
0085    #else
0086       #define BOOST_INTERPROCESS_READ_WRITE_BARRIER __asm__ __volatile__("" : : : "memory")
0087    #endif
0088 #endif
0089 
0090 namespace boost{
0091 namespace interprocess{
0092 namespace ipcdetail{
0093 
0094 //! Atomically decrement an boost::uint32_t by 1
0095 //! "mem": pointer to the atomic value
0096 //! Returns the old value pointed to by mem
0097 inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
0098 {  return (boost::uint32_t)winapi::interlocked_decrement(reinterpret_cast<volatile long*>(mem)) + 1;  }
0099 
0100 //! Atomically increment an apr_uint32_t by 1
0101 //! "mem": pointer to the object
0102 //! Returns the old value pointed to by mem
0103 inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
0104 {  return (boost::uint32_t)winapi::interlocked_increment(reinterpret_cast<volatile long*>(mem))-1;  }
0105 
0106 //! Atomically read an boost::uint32_t from memory
0107 inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
0108 {
0109     const boost::uint32_t val = *mem;
0110     BOOST_INTERPROCESS_READ_WRITE_BARRIER;
0111     return val;
0112 }
0113 
0114 //! Atomically set an boost::uint32_t in memory
0115 //! "mem": pointer to the object
0116 //! "param": val value that the object will assume
0117 inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
0118 {  winapi::interlocked_exchange(reinterpret_cast<volatile long*>(mem), (long)val);  }
0119 
0120 //! Compare an boost::uint32_t's value with "cmp".
0121 //! If they are the same swap the value with "with"
0122 //! "mem": pointer to the value
0123 //! "with": what to swap it with
0124 //! "cmp": the value to compare it to
0125 //! Returns the old value of *mem
0126 inline boost::uint32_t atomic_cas32
0127    (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
0128 {  return (boost::uint32_t)winapi::interlocked_compare_exchange(reinterpret_cast<volatile long*>(mem), (long)with, (long)cmp);  }
0129 
0130 }  //namespace ipcdetail{
0131 }  //namespace interprocess{
0132 }  //namespace boost{
0133 
0134 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && !defined(_CRAYC)
0135 
0136 namespace boost {
0137 namespace interprocess {
0138 namespace ipcdetail{
0139 
0140 //! Compare an boost::uint32_t's value with "cmp".
0141 //! If they are the same swap the value with "with"
0142 //! "mem": pointer to the value
0143 //! "with" what to swap it with
0144 //! "cmp": the value to compare it to
0145 //! Returns the old value of *mem
0146 inline boost::uint32_t atomic_cas32
0147    (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
0148 {
0149    boost::uint32_t prev = cmp;
0150    // This version by Mans Rullgard of Pathscale
0151    __asm__ __volatile__ ( "lock\n\t"
0152                           "cmpxchg %2,%0"
0153                         : "+m"(*mem), "+a"(prev)
0154                         : "r"(with)
0155                         : "cc");
0156 
0157    return prev;
0158 }
0159 
0160 //! Atomically add 'val' to an boost::uint32_t
0161 //! "mem": pointer to the object
0162 //! "val": amount to add
0163 //! Returns the old value pointed to by mem
0164 inline boost::uint32_t atomic_add32
0165    (volatile boost::uint32_t *mem, boost::uint32_t val)
0166 {
0167    // int r = *pw;
0168    // *mem += val;
0169    // return r;
0170    boost::uint32_t r;
0171 
0172    asm volatile
0173    (
0174       "lock\n\t"
0175       "xadd %1, %0":
0176       "+m"( *mem ), "=r"( r ): // outputs (%0, %1)
0177       "1"( val ): // inputs (%2 == %1)
0178       "memory", "cc" // clobbers
0179    );
0180 
0181    return r;
0182 }
0183 
0184 //! Atomically increment an apr_uint32_t by 1
0185 //! "mem": pointer to the object
0186 //! Returns the old value pointed to by mem
0187 inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
0188 {  return atomic_add32(mem, 1);  }
0189 
0190 //! Atomically decrement an boost::uint32_t by 1
0191 //! "mem": pointer to the atomic value
0192 //! Returns the old value pointed to by mem
0193 inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
0194 {  return atomic_add32(mem, (boost::uint32_t)-1);  }
0195 
0196 //! Atomically read an boost::uint32_t from memory
0197 inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
0198 {
0199    const boost::uint32_t val = *mem;
0200    __asm__ __volatile__ ( "" ::: "memory" );
0201    return val;
0202 }
0203 
0204 //! Atomically set an boost::uint32_t in memory
0205 //! "mem": pointer to the object
0206 //! "param": val value that the object will assume
0207 inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
0208 {
0209    __asm__ __volatile__
0210    (
0211       "xchgl %0, %1"
0212       : "+r" (val), "+m" (*mem)
0213       :: "memory"
0214    );
0215 }
0216 
0217 }  //namespace ipcdetail{
0218 }  //namespace interprocess{
0219 }  //namespace boost{
0220 
0221 #elif defined(__GNUC__) && (defined(__PPC__) || defined(__ppc__))
0222 
0223 namespace boost {
0224 namespace interprocess {
0225 namespace ipcdetail{
0226 
0227 //! Atomically add 'val' to an boost::uint32_t
0228 //! "mem": pointer to the object
0229 //! "val": amount to add
0230 //! Returns the old value pointed to by mem
0231 inline boost::uint32_t atomic_add32(volatile boost::uint32_t *mem, boost::uint32_t val)
0232 {
0233    boost::uint32_t prev, temp;
0234 
0235    asm volatile
0236      (
0237          BOOST_INTERPROCESS_DETAIL_PPC_ASM_LABEL("1")
0238          "lwarx  %0,0,%2\n\t"
0239          "add    %1,%0,%3\n\t"
0240          "stwcx. %1,0,%2\n\t"
0241          BOOST_INTERPROCESS_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12")
0242          : "=&r" (prev), "=&r" (temp)
0243          : "b" (mem), "r" (val)
0244          : "cc", "memory"
0245       );
0246    return prev;
0247 }
0248 
0249 //! Compare an boost::uint32_t's value with "cmp".
0250 //! If they are the same swap the value with "with"
0251 //! "mem": pointer to the value
0252 //! "with" what to swap it with
0253 //! "cmp": the value to compare it to
0254 //! Returns the old value of *mem
0255 inline boost::uint32_t atomic_cas32
0256    (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
0257 {
0258    boost::uint32_t prev;
0259 
0260    asm volatile
0261      (
0262          BOOST_INTERPROCESS_DETAIL_PPC_ASM_LABEL("1")
0263          "lwarx  %0,0,%1\n\t"
0264          "cmpw   %0,%3\n\t"
0265          BOOST_INTERPROCESS_DETAIL_PPC_ASM_JUMP("bne-", "2f", "+12")
0266          "stwcx. %2,0,%1\n\t"
0267          BOOST_INTERPROCESS_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-16")
0268          BOOST_INTERPROCESS_DETAIL_PPC_ASM_LABEL("2")
0269          : "=&r"(prev)
0270      : "b" (mem), "r" (with), "r" (cmp)
0271      : "cc", "memory"
0272       );
0273    return prev;
0274 }
0275 
0276 //! Atomically increment an apr_uint32_t by 1
0277 //! "mem": pointer to the object
0278 //! Returns the old value pointed to by mem
0279 inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
0280 {  return atomic_add32(mem, 1);  }
0281 
0282 //! Atomically decrement an boost::uint32_t by 1
0283 //! "mem": pointer to the atomic value
0284 //! Returns the old value pointed to by mem
0285 inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
0286 {  return atomic_add32(mem, boost::uint32_t(-1u));  }
0287 
0288 //! Atomically read an boost::uint32_t from memory
0289 inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
0290 {
0291    const boost::uint32_t val = *mem;
0292    __asm__ __volatile__ ( "" ::: "memory" );
0293    return val;
0294 }
0295 
0296 //! Atomically set an boost::uint32_t in memory
0297 //! "mem": pointer to the object
0298 //! "param": val value that the object will assume
0299 inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
0300 {  *mem = val; }
0301 
0302 }  //namespace ipcdetail{
0303 }  //namespace interprocess{
0304 }  //namespace boost{
0305 
0306 #elif (defined(sun) || defined(__sun))
0307 
0308 #include <atomic.h>
0309 
0310 namespace boost{
0311 namespace interprocess{
0312 namespace ipcdetail{
0313 
0314 //! Atomically add 'val' to an boost::uint32_t
0315 //! "mem": pointer to the object
0316 //! "val": amount to add
0317 //! Returns the old value pointed to by mem
0318 inline boost::uint32_t atomic_add32(volatile boost::uint32_t *mem, boost::uint32_t val)
0319 {   return atomic_add_32_nv(reinterpret_cast<volatile ::uint32_t*>(mem), (int32_t)val) - val;   }
0320 
0321 //! Compare an boost::uint32_t's value with "cmp".
0322 //! If they are the same swap the value with "with"
0323 //! "mem": pointer to the value
0324 //! "with" what to swap it with
0325 //! "cmp": the value to compare it to
0326 //! Returns the old value of *mem
0327 inline boost::uint32_t atomic_cas32
0328    (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
0329 {  return atomic_cas_32(reinterpret_cast<volatile ::uint32_t*>(mem), cmp, with);  }
0330 
0331 //! Atomically increment an apr_uint32_t by 1
0332 //! "mem": pointer to the object
0333 //! Returns the old value pointed to by mem
0334 inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
0335 {  return atomic_add_32_nv(reinterpret_cast<volatile ::uint32_t*>(mem), 1) - 1; }
0336 
0337 //! Atomically decrement an boost::uint32_t by 1
0338 //! "mem": pointer to the atomic value
0339 //! Returns the old value pointed to by mem
0340 inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
0341 {  return atomic_add_32_nv(reinterpret_cast<volatile ::uint32_t*>(mem), (boost::uint32_t)-1) + 1; }
0342 
0343 //! Atomically read an boost::uint32_t from memory
0344 inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
0345 {  return *mem;   }
0346 
0347 //! Atomically set an boost::uint32_t in memory
0348 //! "mem": pointer to the object
0349 //! "param": val value that the object will assume
0350 inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
0351 {  *mem = val; }
0352 
0353 }  //namespace ipcdetail{
0354 }  //namespace interprocess{
0355 }  //namespace boost{
0356 
0357 #elif defined(__osf__) && defined(__DECCXX)
0358 
0359 #include <machine/builtins.h>
0360 #include <c_asm.h>
0361 
0362 namespace boost{
0363 namespace interprocess{
0364 namespace ipcdetail{
0365 
0366 //! Atomically decrement a uint32_t by 1
0367 //! "mem": pointer to the atomic value
0368 //! Returns the old value pointed to by mem
0369 //! Acquire, memory barrier after decrement.
0370 inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
0371 {  boost::uint32_t old_val = __ATOMIC_DECREMENT_LONG(mem); __MB(); return old_val; }
0372 
0373 //! Atomically increment a uint32_t by 1
0374 //! "mem": pointer to the object
0375 //! Returns the old value pointed to by mem
0376 //! Release, memory barrier before increment.
0377 inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
0378 {  __MB(); return __ATOMIC_INCREMENT_LONG(mem); }
0379 
0380 // Rational for the implementation of the atomic read and write functions.
0381 //
0382 // 1. The Alpha Architecture Handbook requires that access to a byte,
0383 // an aligned word, an aligned longword, or an aligned quadword is
0384 // atomic. (See 'Alpha Architecture Handbook', version 4, chapter 5.2.2.)
0385 //
0386 // 2. The CXX User's Guide states that volatile quantities are accessed
0387 // with single assembler instructions, and that a compilation error
0388 // occurs when declaring a quantity as volatile which is not properly
0389 // aligned.
0390 
0391 //! Atomically read an boost::uint32_t from memory
0392 //! Acquire, memory barrier after load.
0393 inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
0394 {  boost::uint32_t old_val = *mem; __MB(); return old_val;  }
0395 
0396 //! Atomically set an boost::uint32_t in memory
0397 //! "mem": pointer to the object
0398 //! "param": val value that the object will assume
0399 //! Release, memory barrier before store.
0400 inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
0401 {  __MB(); *mem = val; }
0402 
0403 //! Compare an boost::uint32_t's value with "cmp".
0404 //! If they are the same swap the value with "with"
0405 //! "mem": pointer to the value
0406 //! "with" what to swap it with
0407 //! "cmp": the value to compare it to
0408 //! Returns the old value of *mem
0409 //! Memory barrier between load and store.
0410 inline boost::uint32_t atomic_cas32(
0411   volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
0412 {
0413   // Note:
0414   //
0415   // Branch prediction prefers backward branches, and the Alpha Architecture
0416   // Handbook explicitely states that the loop should not be implemented like
0417   // it is below. (See chapter 4.2.5.) Therefore the code should probably look
0418   // like this:
0419   //
0420   // return asm(
0421   //   "10: ldl_l %v0,(%a0) ;"
0422   //   "    cmpeq %v0,%a2,%t0 ;"
0423   //   "    beq %t0,20f ;"
0424   //   "    mb ;"
0425   //   "    mov %a1,%t0 ;"
0426   //   "    stl_c %t0,(%a0) ;"
0427   //   "    beq %t0,30f ;"
0428   //   "20: ret ;"
0429   //   "30: br 10b;",
0430   //   mem, with, cmp);
0431   //
0432   // But as the compiler always transforms this into the form where a backward
0433   // branch is taken on failure, we can as well implement it in the straight
0434   // forward form, as this is what it will end up in anyway.
0435 
0436   return asm(
0437     "10: ldl_l %v0,(%a0) ;"    // load prev value from mem and lock mem
0438     "    cmpeq %v0,%a2,%t0 ;"  // compare with given value
0439     "    beq %t0,20f ;"        // if not equal, we're done
0440     "    mb ;"                 // memory barrier
0441     "    mov %a1,%t0 ;"        // load new value into scratch register
0442     "    stl_c %t0,(%a0) ;"    // store new value to locked mem (overwriting scratch)
0443     "    beq %t0,10b ;"        // store failed because lock has been stolen, retry
0444     "20: ",
0445     mem, with, cmp);
0446 }
0447 
0448 }  //namespace ipcdetail{
0449 }  //namespace interprocess{
0450 }  //namespace boost{
0451 
0452 #elif defined(__IBMCPP__) && (__IBMCPP__ >= 800) && defined(_AIX)
0453 
0454 #include <builtins.h>
0455 
0456 namespace boost {
0457 namespace interprocess {
0458 namespace ipcdetail{
0459 
0460 //first define boost::uint32_t versions of __lwarx and __stwcx to avoid poluting
0461 //all the functions with casts
0462 
0463 //! From XLC documenation :
0464 //! This function can be used with a subsequent stwcxu call to implement a
0465 //! read-modify-write on a specified memory location. The two functions work
0466 //! together to ensure that if the store is successfully performed, no other
0467 //! processor or mechanism can modify the target doubleword between the time
0468 //! lwarxu function is executed and the time the stwcxu functio ncompletes.
0469 //! "mem" : pointer to the object
0470 //! Returns the value at pointed to by mem
0471 inline boost::uint32_t lwarxu(volatile boost::uint32_t *mem)
0472 {
0473    return static_cast<boost::uint32_t>(__lwarx(reinterpret_cast<volatile int*>(mem)));
0474 }
0475 
0476 //! "mem" : pointer to the object
0477 //! "val" : the value to store
0478 //! Returns true if the update of mem is successful and false if it is
0479 //!unsuccessful
0480 inline bool stwcxu(volatile boost::uint32_t* mem, boost::uint32_t val)
0481 {
0482    return (__stwcx(reinterpret_cast<volatile int*>(mem), static_cast<int>(val)) != 0);
0483 }
0484 
0485 //! "mem": pointer to the object
0486 //! "val": amount to add
0487 //! Returns the old value pointed to by mem
0488 inline boost::uint32_t atomic_add32
0489    (volatile boost::uint32_t *mem, boost::uint32_t val)
0490 {
0491    boost::uint32_t oldValue;
0492    do
0493    {
0494       oldValue = lwarxu(mem);
0495    }while (!stwcxu(mem, oldValue+val));
0496    return oldValue;
0497 }
0498 
0499 //! Atomically increment an apr_uint32_t by 1
0500 //! "mem": pointer to the object
0501 //! Returns the old value pointed to by mem
0502 inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
0503 {  return atomic_add32(mem, 1);  }
0504 
0505 //! Atomically decrement an boost::uint32_t by 1
0506 //! "mem": pointer to the atomic value
0507 //! Returns the old value pointed to by mem
0508 inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
0509 {  return atomic_add32(mem, (boost::uint32_t)-1);   }
0510 
0511 //! Atomically read an boost::uint32_t from memory
0512 inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
0513 {  return *mem;   }
0514 
0515 //! Compare an boost::uint32_t's value with "cmp".
0516 //! If they are the same swap the value with "with"
0517 //! "mem": pointer to the value
0518 //! "with" what to swap it with
0519 //! "cmp": the value to compare it to
0520 //! Returns the old value of *mem
0521 inline boost::uint32_t atomic_cas32
0522    (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
0523 {
0524    boost::uint32_t oldValue;
0525    boost::uint32_t valueToStore;
0526    do
0527    {
0528       oldValue = lwarxu(mem);
0529    } while (!stwcxu(mem, (oldValue == with) ? cmp : oldValue));
0530 
0531    return oldValue;
0532 }
0533 
0534 //! Atomically set an boost::uint32_t in memory
0535 //! "mem": pointer to the object
0536 //! "param": val value that the object will assume
0537 inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
0538 {  *mem = val; }
0539 
0540 }  //namespace ipcdetail
0541 }  //namespace interprocess
0542 }  //namespace boost
0543 
0544 #elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 )
0545 
0546 namespace boost {
0547 namespace interprocess {
0548 namespace ipcdetail{
0549 
0550 //! Atomically add 'val' to an boost::uint32_t
0551 //! "mem": pointer to the object
0552 //! "val": amount to add
0553 //! Returns the old value pointed to by mem
0554 inline boost::uint32_t atomic_add32
0555    (volatile boost::uint32_t *mem, boost::uint32_t val)
0556 {  return __sync_fetch_and_add(const_cast<boost::uint32_t *>(mem), val);   }
0557 
0558 //! Atomically increment an apr_uint32_t by 1
0559 //! "mem": pointer to the object
0560 //! Returns the old value pointed to by mem
0561 inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
0562 {  return atomic_add32(mem, 1);  }
0563 
0564 //! Atomically decrement an boost::uint32_t by 1
0565 //! "mem": pointer to the atomic value
0566 //! Returns the old value pointed to by mem
0567 inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
0568 {  return atomic_add32(mem, (boost::uint32_t)-1);   }
0569 
0570 //! Atomically read an boost::uint32_t from memory
0571 inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
0572 {  boost::uint32_t old_val = *mem; __sync_synchronize(); return old_val;  }
0573 
0574 //! Compare an boost::uint32_t's value with "cmp".
0575 //! If they are the same swap the value with "with"
0576 //! "mem": pointer to the value
0577 //! "with" what to swap it with
0578 //! "cmp": the value to compare it to
0579 //! Returns the old value of *mem
0580 inline boost::uint32_t atomic_cas32
0581    (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
0582 {  return __sync_val_compare_and_swap(const_cast<boost::uint32_t *>(mem), cmp, with);   }
0583 
0584 //! Atomically set an boost::uint32_t in memory
0585 //! "mem": pointer to the object
0586 //! "param": val value that the object will assume
0587 inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
0588 {  __sync_synchronize(); *mem = val;  }
0589 
0590 }  //namespace ipcdetail{
0591 }  //namespace interprocess{
0592 }  //namespace boost{
0593 #elif defined(__VXWORKS__)
0594 
0595 #include <vxAtomicLib.h>
0596 // VxWorks atomic32_t is not volatile, for some unknown reason
0597 #define vx_atomic_cast(_i)   (reinterpret_cast< ::atomic32_t *>( const_cast<boost::uint32_t *>(_i)))
0598 
0599 namespace boost {
0600 namespace interprocess {
0601 namespace ipcdetail{
0602 
0603 //! Atomically add 'val' to an boost::uint32_t
0604 //! "mem": pointer to the object
0605 //! "val": amount to add
0606 //! Returns the old value pointed to by mem
0607 inline boost::uint32_t atomic_add32
0608    (volatile boost::uint32_t *mem, boost::uint32_t val)
0609 {  return ::vxAtomic32Add( vx_atomic_cast(mem), val);   }
0610 
0611 //! Atomically increment an apr_uint32_t by 1
0612 //! "mem": pointer to the object
0613 //! Returns the old value pointed to by mem
0614 inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
0615 {  return ::vxAtomic32Inc( vx_atomic_cast(mem) );  }
0616 
0617 //! Atomically decrement an boost::uint32_t by 1
0618 //! "mem": pointer to the atomic value
0619 //! Returns the old value pointed to by mem
0620 inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
0621 {  return ::vxAtomic32Dec( vx_atomic_cast(mem) );   }
0622 
0623 //! Atomically read an boost::uint32_t from memory
0624 inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
0625 {  return ::vxAtomic32Get( vx_atomic_cast(mem) );  }
0626 
0627 //! Compare an boost::uint32_t's value with "cmp".
0628 //! If they are the same swap the value with "with"
0629 //! "mem": pointer to the value
0630 //! "with" what to swap it with
0631 //! "cmp": the value to compare it to
0632 //! Returns the old value of *mem
0633 inline boost::uint32_t atomic_cas32
0634    (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
0635 {  return ::vxAtomic32Cas( vx_atomic_cast(mem), cmp, with);  }
0636 
0637 //! Atomically set an boost::uint32_t in memory
0638 //! "mem": pointer to the object
0639 //! "param": val value that the object will assume
0640 inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
0641 {  ::vxAtomic32Set( vx_atomic_cast(mem), val);  }
0642 
0643 
0644 }  //namespace ipcdetail{
0645 }  //namespace interprocess{
0646 }  //namespace boost{
0647 
0648 #else
0649 
0650 #error No atomic operations implemented for this platform, sorry!
0651 
0652 #endif
0653 
0654 namespace boost{
0655 namespace interprocess{
0656 namespace ipcdetail{
0657 
0658 inline bool atomic_add_unless32
0659    (volatile boost::uint32_t *mem, boost::uint32_t value, boost::uint32_t unless_this)
0660 {
0661    boost::uint32_t old, c(atomic_read32(mem));
0662    while(c != unless_this && (old = atomic_cas32(mem, c + value, c)) != c){
0663       c = old;
0664    }
0665    return c != unless_this;
0666 }
0667 
0668 }  //namespace ipcdetail
0669 }  //namespace interprocess
0670 }  //namespace boost
0671 
0672 
0673 #include <boost/interprocess/detail/config_end.hpp>
0674 
0675 #endif   //BOOST_INTERPROCESS_DETAIL_ATOMIC_HPP