633 CI addend = add_value; |
633 CI addend = add_value; |
634 return PlatformAdd<sizeof(P*)>()(addend, dest, order); |
634 return PlatformAdd<sizeof(P*)>()(addend, dest, order); |
635 } |
635 } |
636 }; |
636 }; |
637 |
637 |
638 // Most platforms do not support atomic add on a 2-byte value. However, |
|
639 // if the value occupies the most significant 16 bits of an aligned 32-bit |
|
640 // word, then we can do this with an atomic add of (add_value << 16) |
|
641 // to the 32-bit word. |
|
642 // |
|
643 // The least significant parts of this 32-bit word will never be affected, even |
|
644 // in case of overflow/underflow. |
|
645 // |
|
646 // Use the ATOMIC_SHORT_PAIR macro (see macros.hpp) to get the desired alignment. |
|
647 template<> |
|
648 struct Atomic::AddImpl<short, short> { |
|
649 short operator()(short add_value, short volatile* dest, atomic_memory_order order) const { |
|
650 #ifdef VM_LITTLE_ENDIAN |
|
651 assert((intx(dest) & 0x03) == 0x02, "wrong alignment"); |
|
652 int new_value = Atomic::add(add_value << 16, (volatile int*)(dest-1), order); |
|
653 #else |
|
654 assert((intx(dest) & 0x03) == 0x00, "wrong alignment"); |
|
655 int new_value = Atomic::add(add_value << 16, (volatile int*)(dest), order); |
|
656 #endif |
|
657 return (short)(new_value >> 16); // preserves sign |
|
658 } |
|
659 }; |
|
660 |
|
661 template<typename Derived> |
638 template<typename Derived> |
662 template<typename I, typename D> |
639 template<typename I, typename D> |
663 inline D Atomic::FetchAndAdd<Derived>::operator()(I add_value, D volatile* dest, |
640 inline D Atomic::FetchAndAdd<Derived>::operator()(I add_value, D volatile* dest, |
664 atomic_memory_order order) const { |
641 atomic_memory_order order) const { |
665 I addend = add_value; |
642 I addend = add_value; |