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