File indexing completed on 2026-09-13 08:49:27
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
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
0044
0045
0046 inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem);
0047
0048
0049 inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem);
0050
0051
0052
0053
0054 inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val);
0055
0056
0057
0058
0059
0060
0061
0062 inline boost::uint32_t atomic_cas32
0063 (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp);
0064
0065 }
0066 }
0067 }
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
0095
0096
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
0101
0102
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
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
0115
0116
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
0121
0122
0123
0124
0125
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 }
0131 }
0132 }
0133
0134 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && !defined(_CRAYC)
0135
0136 namespace boost {
0137 namespace interprocess {
0138 namespace ipcdetail{
0139
0140
0141
0142
0143
0144
0145
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
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
0161
0162
0163
0164 inline boost::uint32_t atomic_add32
0165 (volatile boost::uint32_t *mem, boost::uint32_t val)
0166 {
0167
0168
0169
0170 boost::uint32_t r;
0171
0172 asm volatile
0173 (
0174 "lock\n\t"
0175 "xadd %1, %0":
0176 "+m"( *mem ), "=r"( r ):
0177 "1"( val ):
0178 "memory", "cc"
0179 );
0180
0181 return r;
0182 }
0183
0184
0185
0186
0187 inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
0188 { return atomic_add32(mem, 1); }
0189
0190
0191
0192
0193 inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
0194 { return atomic_add32(mem, (boost::uint32_t)-1); }
0195
0196
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
0205
0206
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 }
0218 }
0219 }
0220
0221 #elif defined(__GNUC__) && (defined(__PPC__) || defined(__ppc__))
0222
0223 namespace boost {
0224 namespace interprocess {
0225 namespace ipcdetail{
0226
0227
0228
0229
0230
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
0250
0251
0252
0253
0254
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
0277
0278
0279 inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
0280 { return atomic_add32(mem, 1); }
0281
0282
0283
0284
0285 inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
0286 { return atomic_add32(mem, boost::uint32_t(-1u)); }
0287
0288
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
0297
0298
0299 inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
0300 { *mem = val; }
0301
0302 }
0303 }
0304 }
0305
0306 #elif (defined(sun) || defined(__sun))
0307
0308 #include <atomic.h>
0309
0310 namespace boost{
0311 namespace interprocess{
0312 namespace ipcdetail{
0313
0314
0315
0316
0317
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
0322
0323
0324
0325
0326
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
0332
0333
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
0338
0339
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
0344 inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
0345 { return *mem; }
0346
0347
0348
0349
0350 inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
0351 { *mem = val; }
0352
0353 }
0354 }
0355 }
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
0367
0368
0369
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
0374
0375
0376
0377 inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
0378 { __MB(); return __ATOMIC_INCREMENT_LONG(mem); }
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
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
0397
0398
0399
0400 inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
0401 { __MB(); *mem = val; }
0402
0403
0404
0405
0406
0407
0408
0409
0410 inline boost::uint32_t atomic_cas32(
0411 volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
0412 {
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436 return asm(
0437 "10: ldl_l %v0,(%a0) ;"
0438 " cmpeq %v0,%a2,%t0 ;"
0439 " beq %t0,20f ;"
0440 " mb ;"
0441 " mov %a1,%t0 ;"
0442 " stl_c %t0,(%a0) ;"
0443 " beq %t0,10b ;"
0444 "20: ",
0445 mem, with, cmp);
0446 }
0447
0448 }
0449 }
0450 }
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
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470
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
0477
0478
0479
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
0486
0487
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
0500
0501
0502 inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
0503 { return atomic_add32(mem, 1); }
0504
0505
0506
0507
0508 inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
0509 { return atomic_add32(mem, (boost::uint32_t)-1); }
0510
0511
0512 inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
0513 { return *mem; }
0514
0515
0516
0517
0518
0519
0520
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
0535
0536
0537 inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
0538 { *mem = val; }
0539
0540 }
0541 }
0542 }
0543
0544 #elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 )
0545
0546 namespace boost {
0547 namespace interprocess {
0548 namespace ipcdetail{
0549
0550
0551
0552
0553
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
0559
0560
0561 inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
0562 { return atomic_add32(mem, 1); }
0563
0564
0565
0566
0567 inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
0568 { return atomic_add32(mem, (boost::uint32_t)-1); }
0569
0570
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
0575
0576
0577
0578
0579
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
0585
0586
0587 inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
0588 { __sync_synchronize(); *mem = val; }
0589
0590 }
0591 }
0592 }
0593 #elif defined(__VXWORKS__)
0594
0595 #include <vxAtomicLib.h>
0596
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
0604
0605
0606
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
0612
0613
0614 inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
0615 { return ::vxAtomic32Inc( vx_atomic_cast(mem) ); }
0616
0617
0618
0619
0620 inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
0621 { return ::vxAtomic32Dec( vx_atomic_cast(mem) ); }
0622
0623
0624 inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
0625 { return ::vxAtomic32Get( vx_atomic_cast(mem) ); }
0626
0627
0628
0629
0630
0631
0632
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
0638
0639
0640 inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
0641 { ::vxAtomic32Set( vx_atomic_cast(mem), val); }
0642
0643
0644 }
0645 }
0646 }
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 }
0669 }
0670 }
0671
0672
0673 #include <boost/interprocess/detail/config_end.hpp>
0674
0675 #endif