Files
oceanbase/deps/oblib/src/lib/atomic/atomic128.h
2022-04-18 15:12:30 +08:00

127 lines
4.6 KiB
C++

/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
#ifndef OCEANBASE_CLOG_ATOMIC128_
#define OCEANBASE_CLOG_ATOMIC128_
#include <cstdint>
namespace types {
struct uint128_t {
uint64_t lo;
uint64_t hi;
} __attribute__((__aligned__(16)));
} // namespace types
#if defined(__x86_64__)
inline bool cas128(volatile types::uint128_t* src, types::uint128_t* cmp, types::uint128_t with)
{
bool result;
__asm__ __volatile__("\n\tlock cmpxchg16b %1"
"\n\tsetz %0\n"
: "=q"(result), "+m"(*src), "+d"(cmp->hi), "+a"(cmp->lo)
: "c"(with.hi), "b"(with.lo)
: "cc");
return result;
}
inline void load128(__uint128_t& dest, types::uint128_t* src)
{
__asm__ __volatile__("\n\txor %%rax, %%rax;"
"\n\txor %%rbx, %%rbx;"
"\n\txor %%rcx, %%rcx;"
"\n\txor %%rdx, %%rdx;"
"\n\tlock cmpxchg16b %1;\n"
: "=&A"(dest)
: "m"(*src)
: "%rbx", "%rcx", "cc");
}
#define CAS128(src, cmp, with) \
cas128((types::uint128_t*)(src), ((types::uint128_t*)&(cmp)), *((types::uint128_t*)&(with)))
#define LOAD128(dest, src) load128((__uint128_t&)(dest), (types::uint128_t*)(src))
#elif defined(__aarch64__)
inline bool cas128(volatile types::uint128_t* target, types::uint128_t* cmp, types::uint128_t with)
{
int ret = 0;
types::uint128_t tmp;
tmp.lo = cmp->lo;
tmp.hi = cmp->hi;
ret = __atomic_compare_exchange((types::uint128_t*)(target),
((types::uint128_t*)&(tmp)),
((types::uint128_t*)&(with)),
false,
__ATOMIC_SEQ_CST,
__ATOMIC_SEQ_CST);
return ret;
}
inline void load128(__uint128_t& target, types::uint128_t* source)
{
__uint128_t* ptr = reinterpret_cast<__uint128_t*>(&target);
__uint128_t* desired = reinterpret_cast<__uint128_t*>(source);
__atomic_load((__uint128_t*)desired, ptr, __ATOMIC_SEQ_CST);
}
#define CAS128_tmp(src, cmp, with) \
cas128((types::uint128_t*)(src), ((types::uint128_t*)(&(cmp))), *((types::uint128_t*)(&(with))))
#define LOAD128_asm(dest, src) load128((__uint128_t&)(dest), ((types::uint128_t*)(src)))
#define CAS128(src, cmp, with) \
__atomic_compare_exchange(((types::uint128_t*)(src)), \
((types::uint128_t*)(&(cmp))), \
((types::uint128_t*)&(with)), \
false, \
__ATOMIC_SEQ_CST, \
__ATOMIC_SEQ_CST)
#define LOAD128(dest, src) __atomic_load(((types::uint128_t*)(src)), ((types::uint128_t*)(&(dest))), __ATOMIC_SEQ_CST)
#elif defined(__sw_64__) || defined(__loongarch64)
inline bool cas128(volatile types::uint128_t* target, types::uint128_t* cmp, types::uint128_t with)
{
int ret = 0;
types::uint128_t tmp;
tmp.lo = cmp->lo;
tmp.hi = cmp->hi;
ret = __atomic_compare_exchange((types::uint128_t*)(target),
((types::uint128_t*)&(tmp)),
((types::uint128_t*)&(with)),
false,
__ATOMIC_SEQ_CST,
__ATOMIC_SEQ_CST);
return ret;
}
inline void load128(__uint128_t& target, types::uint128_t* source)
{
__uint128_t* ptr = reinterpret_cast<__uint128_t*>(&target);
__uint128_t* desired = reinterpret_cast<__uint128_t*>(source);
__atomic_load((__uint128_t*)desired, ptr, __ATOMIC_SEQ_CST);
}
#define CAS128_tmp(src, cmp, with) \
cas128((types::uint128_t*)(src), ((types::uint128_t*)(&(cmp))), *((types::uint128_t*)(&(with))))
#define LOAD128_asm(dest, src) load128((__uint128_t&)(dest), ((types::uint128_t*)(src)))
#define CAS128(src, cmp, with) \
__atomic_compare_exchange(((types::uint128_t*)(src)), \
((types::uint128_t*)(&(cmp))), \
((types::uint128_t*)&(with)), \
false, \
__ATOMIC_SEQ_CST, \
__ATOMIC_SEQ_CST)
#define LOAD128(dest, src) __atomic_load(((types::uint128_t*)(src)), ((types::uint128_t*)(&(dest))), __ATOMIC_SEQ_CST)
#else
#error arch unsupported
#endif
#endif // OCEANBASE_CLOG_ATOMIC128_