Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 27 additions & 16 deletions include/hal.h
Original file line number Diff line number Diff line change
Expand Up @@ -469,19 +469,26 @@ typedef union {
volatile rtapi_port _p; \
}

// Pin values are accessed with relaxed atomics so that a reader in another
// thread never sees half of a write (64-bit values on 32-bit targets). On
// 64-bit targets these compile to plain loads and stores. configure checks
// that 64-bit atomics are lock-free.
#define __HAL_LOAD(m) __atomic_load_n(&((union __hal_mapped_type *)ref)->m, __ATOMIC_RELAXED)
#define __HAL_STORE(m, v) __atomic_store_n(&((union __hal_mapped_type *)ref)->m, (v), __ATOMIC_RELAXED)


// A 'hal_port_t' is a pin reference which content represents
// the integer offset in the HAL shared memory segment to a
// hal_port_shm_t structure.
static inline __HAL_ALWAYS_INLINE rtapi_port hal_get_port(hal_port_t ref) {
__HAL_MAPPED_TYPE;
// cppcheck-suppress dangerousTypeCast
return ((union __hal_mapped_type *)ref)->_p;
return __HAL_LOAD(_p);
}
static inline __HAL_ALWAYS_INLINE rtapi_port hal_set_port(hal_port_t ref, rtapi_port val) {
__HAL_MAPPED_TYPE;
// cppcheck-suppress dangerousTypeCast
((union __hal_mapped_type *)ref)->_p = val;
__HAL_STORE(_p, val);
return val;
}
//
Expand All @@ -496,7 +503,7 @@ static inline __HAL_ALWAYS_INLINE rtapi_s32 hal_get_si32_clamped(const hal_sint_
__HAL_MAPPED_TYPE;
// Down conversion from the larger type
// cppcheck-suppress dangerousTypeCast
rtapi_sint val = ((union __hal_mapped_type *)ref)->_s;
rtapi_sint val = __HAL_LOAD(_s);
if(val <= RTAPI_INT32_MIN) return RTAPI_INT32_MIN;
if(val >= RTAPI_INT32_MAX) return RTAPI_INT32_MAX;
return (rtapi_s32)val;
Expand All @@ -505,81 +512,85 @@ static inline __HAL_ALWAYS_INLINE rtapi_s32 hal_get_si32(const hal_sint_t ref) {
__HAL_MAPPED_TYPE;
// Implicitly Truncated from the larger type
// cppcheck-suppress dangerousTypeCast
return (rtapi_s32)((union __hal_mapped_type *)ref)->_s;
return (rtapi_s32)__HAL_LOAD(_s);
}
static inline __HAL_ALWAYS_INLINE rtapi_s32 hal_set_si32(hal_sint_t ref, rtapi_s32 val) {
__HAL_MAPPED_TYPE;
// cppcheck-suppress dangerousTypeCast
((union __hal_mapped_type *)ref)->_s = val; // Store in the larger type
__HAL_STORE(_s, val); // Store in the larger type
return val;
}
static inline __HAL_ALWAYS_INLINE rtapi_u32 hal_get_ui32_clamped(const hal_uint_t ref) {
__HAL_MAPPED_TYPE;
// Down conversion from the larger type
// cppcheck-suppress dangerousTypeCast
rtapi_uint val = ((union __hal_mapped_type *)ref)->_u;
rtapi_uint val = __HAL_LOAD(_u);
if(val >= RTAPI_UINT32_MAX) return RTAPI_UINT32_MAX;
return (rtapi_u32)val;
}
static inline __HAL_ALWAYS_INLINE rtapi_u32 hal_get_ui32(const hal_uint_t ref) {
__HAL_MAPPED_TYPE;
// Implicitly Truncated from the larger type
// cppcheck-suppress dangerousTypeCast
return (rtapi_u32)((union __hal_mapped_type *)ref)->_u;
return (rtapi_u32)__HAL_LOAD(_u);
}
static inline __HAL_ALWAYS_INLINE rtapi_u32 hal_set_ui32(hal_uint_t ref, rtapi_u32 val) {
__HAL_MAPPED_TYPE;
// cppcheck-suppress dangerousTypeCast
((union __hal_mapped_type *)ref)->_u = val; // Store in the larger type
__HAL_STORE(_u, val); // Store in the larger type
return val;
}
static inline __HAL_ALWAYS_INLINE rtapi_sint hal_get_sint(const hal_sint_t ref) {
__HAL_MAPPED_TYPE;
// cppcheck-suppress dangerousTypeCast
return ((union __hal_mapped_type *)ref)->_s;
return __HAL_LOAD(_s);
}
static inline __HAL_ALWAYS_INLINE rtapi_sint hal_set_sint(hal_sint_t ref, rtapi_sint val) {
__HAL_MAPPED_TYPE;
// cppcheck-suppress dangerousTypeCast
((union __hal_mapped_type *)ref)->_s = val;
__HAL_STORE(_s, val);
return val;
}
static inline __HAL_ALWAYS_INLINE rtapi_uint hal_get_uint(const hal_uint_t ref) {
__HAL_MAPPED_TYPE;
// cppcheck-suppress dangerousTypeCast
return ((union __hal_mapped_type *)ref)->_u;
return __HAL_LOAD(_u);
}
static inline __HAL_ALWAYS_INLINE rtapi_uint hal_set_uint(hal_uint_t ref, rtapi_uint val) {
__HAL_MAPPED_TYPE;
// cppcheck-suppress dangerousTypeCast
((union __hal_mapped_type *)ref)->_u = val;
__HAL_STORE(_u, val);
return val;
}
static inline __HAL_ALWAYS_INLINE rtapi_real hal_get_real(const hal_real_t ref) {
__HAL_MAPPED_TYPE;
rtapi_real val;
// cppcheck-suppress dangerousTypeCast
return ((union __hal_mapped_type *)ref)->_r;
__atomic_load(&((union __hal_mapped_type *)ref)->_r, &val, __ATOMIC_RELAXED);
return val;
}
static inline __HAL_ALWAYS_INLINE rtapi_real hal_set_real(hal_real_t ref, rtapi_real val) {
__HAL_MAPPED_TYPE;
// cppcheck-suppress dangerousTypeCast
((union __hal_mapped_type *)ref)->_r = val;
__atomic_store(&((union __hal_mapped_type *)ref)->_r, &val, __ATOMIC_RELAXED);
return val;
}
static inline __HAL_ALWAYS_INLINE rtapi_bool hal_get_bool(const hal_bool_t ref) {
__HAL_MAPPED_TYPE;
// cppcheck-suppress dangerousTypeCast
return ((union __hal_mapped_type *)ref)->_b;
return __HAL_LOAD(_b);
}
static inline __HAL_ALWAYS_INLINE rtapi_bool hal_set_bool(hal_bool_t ref, rtapi_bool val) {
__HAL_MAPPED_TYPE;
// 'val' is declared bool and will therefore store a one (1)
// or a zero (0) in the larger target. This still works if the
// call is made using an integer type as original argument.
// cppcheck-suppress dangerousTypeCast
((union __hal_mapped_type *)ref)->_u = val;
__HAL_STORE(_u, val);
return val;
Comment thread
BsAtHome marked this conversation as resolved.
}
#undef __HAL_STORE
#undef __HAL_LOAD
#undef __HAL_MAPPED_TYPE

/***********************************************************************
Expand Down
16 changes: 16 additions & 0 deletions src/configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,22 @@ elif ! test `$CC -dumpversion | cut -d '.' -f 1` -gt 2 ; then
AC_MSG_ERROR([Compilers older than gcc 3.x are no longer supported])
fi

#
# HAL pin accessors use 64-bit atomics. A non-lock-free fallback (libatomic)
# uses process-local locks, which do not protect HAL shared memory.
#
AC_MSG_CHECKING([for lock-free 64-bit atomics])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <stdint.h>
_Static_assert(__atomic_always_lock_free(sizeof(int64_t), 0), "64-bit integer");
_Static_assert(__atomic_always_lock_free(sizeof(double), 0), "64-bit double");
Comment thread
BsAtHome marked this conversation as resolved.
]], [[]])],[
AC_MSG_RESULT(yes)
],[
AC_MSG_RESULT(no)
AC_MSG_ERROR([$CC has no lock-free 64-bit atomics for this target. HAL needs them, e.g. i586 or later on x86, ARMv6K or later on ARM.])
])

AC_MSG_CHECKING([for usability of linux/hidraw.h])
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <sys/ioctl.h>
Expand Down
Loading