Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:38:25

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