| | 464 | #elif defined(__IBMCPP__) && (__IBMCPP__ >= 800) && defined(_AIX) |
| | 465 | |
| | 466 | #include <builtins.h> |
| | 467 | |
| | 468 | namespace boost { |
| | 469 | namespace interprocess { |
| | 470 | namespace detail{ |
| | 471 | |
| | 472 | //first define boost::uint32_t versions of __lwarx and __stwcx to avoid poluting |
| | 473 | //all the functions with casts |
| | 474 | |
| | 475 | //! From XLC documenation : |
| | 476 | //! This function can be used with a subsequent stwcxu call to implement a |
| | 477 | //! read-modify-write on a specified memory location. The two functions work |
| | 478 | //! together to ensure that if the store is successfully performed, no other |
| | 479 | //! processor or mechanism can modify the target doubleword between the time |
| | 480 | //! lwarxu function is executed and the time the stwcxu functio ncompletes. |
| | 481 | //! "mem" : pointer to the object |
| | 482 | //! Returns the value at pointed to by mem |
| | 483 | inline boost::uint32_t lwarxu(volatile boost::uint32_t *mem) |
| | 484 | { |
| | 485 | return static_cast<boost::uint32_t>(__lwarx(reinterpret_cast<volatile int*>(mem))); |
| | 486 | } |
| | 487 | |
| | 488 | //! "mem" : pointer to the object |
| | 489 | //! "val" : the value to store |
| | 490 | //! Returns true if the update of mem is successful and false if it is |
| | 491 | //!unsuccessful |
| | 492 | inline bool stwcxu(volatile boost::uint32_t* mem, boost::uint32_t val) |
| | 493 | { |
| | 494 | return (__stwcx(reinterpret_cast<volatile int*>(mem), static_cast<int>(val)) != 0); |
| | 495 | } |
| | 496 | |
| | 497 | //! "mem": pointer to the object |
| | 498 | //! "val": amount to add |
| | 499 | //! Returns the old value pointed to by mem |
| | 500 | inline boost::uint32_t atomic_add32 |
| | 501 | (volatile boost::uint32_t *mem, boost::uint32_t val) |
| | 502 | { |
| | 503 | boost::uint32_t oldValue; |
| | 504 | do |
| | 505 | { |
| | 506 | oldValue = lwarxu(mem); |
| | 507 | }while (!stwcxu(mem, oldValue+val)); |
| | 508 | return oldValue; |
| | 509 | } |
| | 510 | |
| | 511 | //! Atomically increment an apr_uint32_t by 1 |
| | 512 | //! "mem": pointer to the object |
| | 513 | //! Returns the old value pointed to by mem |
| | 514 | inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem) |
| | 515 | { return atomic_add32(mem, 1); } |
| | 516 | |
| | 517 | //! Atomically decrement an boost::uint32_t by 1 |
| | 518 | //! "mem": pointer to the atomic value |
| | 519 | //! Returns the old value pointed to by mem |
| | 520 | inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem) |
| | 521 | { return atomic_add32(mem, (boost::uint32_t)-1); } |
| | 522 | |
| | 523 | //! Atomically read an boost::uint32_t from memory |
| | 524 | inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) |
| | 525 | { return *mem; } |
| | 526 | |
| | 527 | //! Compare an boost::uint32_t's value with "cmp". |
| | 528 | //! If they are the same swap the value with "with" |
| | 529 | //! "mem": pointer to the value |
| | 530 | //! "with" what to swap it with |
| | 531 | //! "cmp": the value to compare it to |
| | 532 | //! Returns the old value of *mem |
| | 533 | inline boost::uint32_t atomic_cas32 |
| | 534 | (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp) |
| | 535 | { |
| | 536 | boost::uint32_t oldValue; |
| | 537 | boost::uint32_t valueToStore; |
| | 538 | do |
| | 539 | { |
| | 540 | oldValue = lwarxu(mem); |
| | 541 | } while (!stwcxu(mem, (oldValue == with) ? cmp : oldValue)); |
| | 542 | |
| | 543 | return oldValue; |
| | 544 | } |
| | 545 | |
| | 546 | //! Atomically set an boost::uint32_t in memory |
| | 547 | //! "mem": pointer to the object |
| | 548 | //! "param": val value that the object will assume |
| | 549 | inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val) |
| | 550 | { *mem = val; } |
| | 551 | |
| | 552 | } //namespace detail |
| | 553 | } //namespace interprocess |
| | 554 | } //namespace boost |
| | 555 | |