192 lines
5.9 KiB
C
Executable File
192 lines
5.9 KiB
C
Executable File
// 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
|