void Interlocked::cas (Data128 &old, volatile Data128 &dest, const Data128 &excg, const Data128 &comp) { assert (&old != 0); assert (is_ptr_aligned_nz (&dest)); #if ((_MSC_VER / 100) >= 15) // VC2008 or above const int64_t excg_lo = ((const int64_t *) &excg) [0]; const int64_t excg_hi = ((const int64_t *) &excg) [1]; old = comp; _InterlockedCompareExchange128 ( reinterpret_cast <volatile int64_t *> (&dest), excg_hi, excg_lo, reinterpret_cast <int64_t *> (&old) ); #else /*** To do ***/ #error Requires assembly code #endif }
void *LFListBase::pop() { while (true) { Data oldDatas = _datas; Data datas = _datas; if (datas.head != nullptr) { void *res = (void*)(datas.head); datas.size -= 1; datas.head = (void*)(*(__int64*)((void*)((size_t)(res)+_nextPtrPadding))); __int64 comparandResult[2]; comparandResult[0] = (__int64)oldDatas.size; /* low */ comparandResult[1] = (__int64)oldDatas.head; /* high */ if (_InterlockedCompareExchange128( &_datas.size, (__int64)datas.head, datas.size, &comparandResult[0] ) == 1) { return res; } } else { return nullptr; } } }
void LFListBase::push(void *element) { void *elementNext = (void*)((std::size_t)element + _nextPtrPadding); while (true) { Data datas; while (true) { datas = _datas; __int64 cr[2]; cr[0] = (__int64)datas.size; /* low */ cr[1] = (__int64)datas.head; /* high */ if (_InterlockedCompareExchange128(&_datas.size, (__int64)datas.head, datas.size, &cr[0]) == 1) { break; } } Data oldDatas = datas; *(std::size_t*)(elementNext) = (std::size_t)datas.head; AGE_ASSERT((std::size_t)(elementNext) % 8 == 0); AGE_ASSERT(datas.head != elementNext); datas.head = element; datas.size += 1; __int64 comparandResult[2]; comparandResult[0] = (__int64)oldDatas.size; /* low */ comparandResult[1] = (__int64)oldDatas.head; /* high */ if (_InterlockedCompareExchange128( &_datas.size, (__int64)datas.head, datas.size, &comparandResult[0] ) == 1) { return; } } }
KOKKOS_INLINE_FUNCTION T atomic_compare_exchange(volatile T * const dest, const T & compare, typename Kokkos::Impl::enable_if< sizeof(T) == sizeof(Impl::cas128_t), const T & >::type val) { union U { Impl::cas128_t i; T t; KOKKOS_INLINE_FUNCTION U() {}; } tmp, newval; newval.t = val; tmp.i = _InterlockedCompareExchange128((LONGLONG*)dest, newval.i.upper, newval.i.lower, *((LONGLONG*)&compare)); return tmp.t; }
inline bool CAS(Ptr<T> &destination, const Ptr<T> &expected, const Ptr<T> &replacement) { #if defined(ARCH_64) Ptr<T> ComparandResult; ComparandResult.N[0] = expected.N[0]; ComparandResult.N[1] = expected.N[1]; // NOTE: Requires VS.NET 2008 or newer return 1 == _InterlockedCompareExchange128((__int64*)destination.N, replacement.N[1], replacement.N[0], (__int64*)ComparandResult.N); #else return expected.N == _InterlockedCompareExchange64((LONGLONG*)&destination.N, replacement.N, expected.N); #endif }
void compareSwapTs(Timestamp *dest, Timestamp *src, int chk) { Timestamp cmp[1]; do { cmp->epoch = dest->epoch; cmp->lowBits = dest->lowBits; if (chk > 0 && compareTs(cmp, src) <= 0) return; if (chk < 0 && compareTs(cmp, src) >= 0) return; #ifdef _WIN32 } while (!_InterlockedCompareExchange128((uint64_t *)dest, src->epoch, src->lowBits, (uint64_t *)cmp) ); #else } while (!__atomic_compare_exchange((__int128 *)dest, (__int128 *)cmp, (__int128 *)src, false, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE));