You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

192 lines
5.9 KiB
C

// SPDX-License-Identifier: LGPL-3.0-or-later
/**
* \file sys/interlocked_ops_gcc.h
*
* Generates interlocked functions from GCC intrinsics, based on some macros.
*
* \copyright The DoubleFourteen Code Forge (C) All Rights Reserved
* \author Lorenzo Cogotti
*
* This file should be `#include`d from `interlocked.h`, on GNUC compilers.
* It generated interlocked primitives based on `INTERLOCKED_TYPE`,
* `INTERLOCKED_SUFFIX` macros.
* `#define`ing `INTERLOCKED_NO_ARIT` disables arithmetic functions
* generation.
* File may be `#include`d multiple times.
*/
#ifndef DF_SYS_INTERLOCKED_H_
#error "Use interlocked.h, do not include interlocked_gcc_ops.h directly"
#endif
#ifndef INTERLOCKED_TYPE
#error "Please define INTERLOCKED_TYPE for atomic operation target type"
#endif
#ifndef INTERLOCKED_SUFFIX
#error "Please define INTERLOCKED_SUFFIX for atomic operation suffix"
#endif
#define _PASTE(a, b) a ## b
#define _XPASTE(a, b) _PASTE(a, b)
#define _FNAME(wk, name, memory_order) \
_XPASTE(_XPASTE(Smp_ ## wk ## Atomic ## name, INTERLOCKED_SUFFIX), memory_order)
#define _FOP(op, memory_order, ...) \
__atomic_ ## op (__VA_ARGS__, __ATOMIC_ ## memory_order)
#define _FCAS(wkflag, succ_memory_order, fail_memory_order, ...) \
__atomic_compare_exchange_n(__VA_ARGS__, wkflag, __ATOMIC_ ## succ_memory_order, __ATOMIC_ ## fail_memory_order)
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Load,) (INTERLOCKED_TYPE *_p)
{
return _FOP(load_n, SEQ_CST, _p);
}
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Load,Rx) (INTERLOCKED_TYPE *_p)
{
return _FOP(load_n, RELAXED, _p);
}
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Load,Acq) (INTERLOCKED_TYPE *_p)
{
return _FOP(load_n, ACQUIRE, _p);
}
FORCE_INLINE void _FNAME(,Store,) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _v)
{
_FOP(store_n, SEQ_CST, _p, _v);
}
FORCE_INLINE void _FNAME(,Store,Rx) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _v)
{
_FOP(store_n, RELAXED, _p, _v);
}
FORCE_INLINE void _FNAME(,Store,Rel) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _v)
{
_FOP(store_n, RELEASE, _p, _v);
}
#ifndef INTERLOCKED_NO_ARIT
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Add,) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _v)
{
return _FOP(add_fetch, ACQ_REL, _p, _v);
}
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Add,Rx) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _v)
{
return _FOP(add_fetch, RELAXED, _p, _v);
}
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Add,Acq) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _v)
{
return _FOP(add_fetch, ACQUIRE, _p, _v);
}
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Add,Rel) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _v)
{
return _FOP(add_fetch, RELEASE, _p, _v);
}
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Sub,) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _v)
{
return _FOP(sub_fetch, ACQ_REL, _p, _v);
}
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Sub,Rx) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _v)
{
return _FOP(sub_fetch, RELAXED, _p, _v);
}
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Sub,Acq) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _v)
{
return _FOP(sub_fetch, ACQUIRE, _p, _v);
}
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Sub,Rel) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _v)
{
return _FOP(sub_fetch, RELEASE, _p, _v);
}
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Incr,) (INTERLOCKED_TYPE *_p)
{
return _FOP(fetch_add, ACQ_REL, _p, 1);
}
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Incr,Rx) (INTERLOCKED_TYPE *_p)
{
return _FOP(fetch_add, RELAXED, _p, 1);
}
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Incr,Acq) (INTERLOCKED_TYPE *_p)
{
return _FOP(fetch_add, ACQUIRE, _p, 1);
}
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Incr,Rel) (INTERLOCKED_TYPE *_p)
{
return _FOP(fetch_add, RELEASE, _p, 1);
}
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Decr,) (INTERLOCKED_TYPE *_p)
{
return _FOP(fetch_sub, ACQ_REL, _p, 1);
}
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Decr,Rx) (INTERLOCKED_TYPE *_p)
{
return _FOP(fetch_sub, RELAXED, _p, 1);
}
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Decr,Acq) (INTERLOCKED_TYPE *_p)
{
return _FOP(fetch_sub, ACQUIRE, _p, 1);
}
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Decr,Rel) (INTERLOCKED_TYPE *_p)
{
return _FOP(fetch_sub, RELEASE, _p, 1);
}
#endif /* INTERLOCKED_NO_ARIT */
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Xchng,) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _v)
{
return _FOP(exchange_n, ACQ_REL, _p, _v);
}
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Xchng,Rx) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _v)
{
return _FOP(exchange_n, RELAXED, _p, _v);
}
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Xchng,Acq) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _v)
{
return _FOP(exchange_n, ACQUIRE, _p, _v);
}
FORCE_INLINE INTERLOCKED_TYPE _FNAME(,Xchng,Rel) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _v)
{
return _FOP(exchange_n, RELEASE, _p, _v);
}
FORCE_INLINE Boolean _FNAME(,Cas,) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _e, INTERLOCKED_TYPE _v)
{
return _FCAS(FALSE, ACQ_REL, ACQUIRE, _p, &_e, _v);
}
FORCE_INLINE Boolean _FNAME(,Cas,Rx) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _e, INTERLOCKED_TYPE _v)
{
return _FCAS(FALSE, RELAXED, RELAXED, _p, &_e, _v);
}
FORCE_INLINE Boolean _FNAME(,Cas,Acq) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _e, INTERLOCKED_TYPE _v)
{
return _FCAS(FALSE, ACQUIRE, ACQUIRE, _p, &_e, _v);
}
FORCE_INLINE Boolean _FNAME(,Cas,Rel) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _e, INTERLOCKED_TYPE _v)
{
return _FCAS(FALSE, RELEASE, RELAXED, _p, &_e, _v);
}
FORCE_INLINE Boolean _FNAME(Wk,Cas,) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _e, INTERLOCKED_TYPE _v)
{
return _FCAS(TRUE, ACQ_REL, ACQUIRE, _p, &_e, _v);
}
FORCE_INLINE Boolean _FNAME(Wk,Cas,Rx) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _e, INTERLOCKED_TYPE _v)
{
return _FCAS(TRUE, RELAXED, RELAXED, _p, &_e, _v);
}
FORCE_INLINE Boolean _FNAME(Wk,Cas,Acq) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _e, INTERLOCKED_TYPE _v)
{
return _FCAS(TRUE, ACQUIRE, ACQUIRE, _p, &_e, _v);
}
FORCE_INLINE Boolean _FNAME(Wk,Xchng,Rel) (INTERLOCKED_TYPE *_p, INTERLOCKED_TYPE _e, INTERLOCKED_TYPE _v)
{
return _FCAS(TRUE, RELEASE, RELAXED, _p, &_e, _v);
}
#undef _PASTE
#undef _XPASTE
#undef _FNAME
#undef _FOP
#undef _FCAS