Implement ck_pr_dec_is_zero family of functions (#115)

* Implement ck_pr_dec_is_zero family of functions
* include/ck_pr.h: add ck_pr_{dec,inc}_is_zero and implement ck_pr_{dec,inc}_zero in terms of the new functions. Convert the architecture-specific implementations of ck_pr_foo_zero for x86 and x86-64 to ck_pr_foo_is_zero.
* regressions/ck_pr/validate: add smoke tests for ck_pr_dec_{,is_}zero and ck_pr_inc_{,is_}zero
* doc: document ck_pr_inc_is_zero
awsm
Theo Schlossnagle 7 years ago committed by Samy Al Bahra
parent 0f017230cc
commit 1c2469358e

@ -29,22 +29,31 @@
.Sh NAME .Sh NAME
.Nm ck_pr_dec_ptr , .Nm ck_pr_dec_ptr ,
.Nm ck_pr_dec_ptr_zero , .Nm ck_pr_dec_ptr_zero ,
.Nm ck_pr_dec_ptr_is_zero ,
.Nm ck_pr_dec_double , .Nm ck_pr_dec_double ,
.Nm ck_pr_dec_double_zero , .Nm ck_pr_dec_double_zero ,
.Nm ck_pr_dec_double_is_zero ,
.Nm ck_pr_dec_char , .Nm ck_pr_dec_char ,
.Nm ck_pr_dec_char_zero , .Nm ck_pr_dec_char_zero ,
.Nm ck_pr_dec_char_is_zero ,
.Nm ck_pr_dec_uint , .Nm ck_pr_dec_uint ,
.Nm ck_pr_dec_uint_zero , .Nm ck_pr_dec_uint_zero ,
.Nm ck_pr_dec_char_is_zero ,
.Nm ck_pr_dec_int , .Nm ck_pr_dec_int ,
.Nm ck_pr_dec_int_zero , .Nm ck_pr_dec_int_zero ,
.Nm ck_pr_dec_int_is_zero ,
.Nm ck_pr_dec_64 , .Nm ck_pr_dec_64 ,
.Nm ck_pr_dec_64_zero , .Nm ck_pr_dec_64_zero ,
.Nm ck_pr_dec_64_is_zero ,
.Nm ck_pr_dec_32 , .Nm ck_pr_dec_32 ,
.Nm ck_pr_dec_32_zero , .Nm ck_pr_dec_32_zero ,
.Nm ck_pr_dec_32_is_zero ,
.Nm ck_pr_dec_16 , .Nm ck_pr_dec_16 ,
.Nm ck_pr_dec_16_zero , .Nm ck_pr_dec_16_zero ,
.Nm ck_pr_dec_32_is_zero ,
.Nm ck_pr_dec_8 , .Nm ck_pr_dec_8 ,
.Nm ck_pr_dec_8_zero .Nm ck_pr_dec_8_zero ,
.Nm ck_pr_dec_8_is_zero
.Nd atomic decrement operations .Nd atomic decrement operations
.Sh LIBRARY .Sh LIBRARY
Concurrency Kit (libck, \-lck) Concurrency Kit (libck, \-lck)
@ -54,38 +63,56 @@ Concurrency Kit (libck, \-lck)
.Fn ck_pr_dec_ptr "void *target" .Fn ck_pr_dec_ptr "void *target"
.Ft void .Ft void
.Fn ck_pr_dec_ptr_zero "void *target" "bool *z" .Fn ck_pr_dec_ptr_zero "void *target" "bool *z"
.Ft bool
.Fn ck_pr_dec_ptr_is_zero "void *target"
.Ft void .Ft void
.Fn ck_pr_dec_double "double *target" .Fn ck_pr_dec_double "double *target"
.Ft void .Ft void
.Fn ck_pr_dec_double_zero "double *target" "bool *z" .Fn ck_pr_dec_double_zero "double *target" "bool *z"
.Ft bool
.Fn ck_pr_dec_double_is_zero "double *target"
.Ft void .Ft void
.Fn ck_pr_dec_char "char *target" .Fn ck_pr_dec_char "char *target"
.Ft void .Ft void
.Fn ck_pr_dec_char_zero "char *target" "bool *z" .Fn ck_pr_dec_char_zero "char *target" "bool *z"
.Ft bool
.Fn ck_pr_dec_char_is_zero "char *target"
.Ft void .Ft void
.Fn ck_pr_dec_uint "unsigned int *target" .Fn ck_pr_dec_uint "unsigned int *target"
.Ft void .Ft void
.Fn ck_pr_dec_uint_zero "unsigned int *target" "bool *z" .Fn ck_pr_dec_uint_zero "unsigned int *target" "bool *z"
.Ft bool
.Fn ck_pr_dec_uint_is_zero "unsigned int *target"
.Ft void .Ft void
.Fn ck_pr_dec_int "int *target" .Fn ck_pr_dec_int "int *target"
.Ft void .Ft void
.Fn ck_pr_dec_int_zero "int *target" "bool *z" .Fn ck_pr_dec_int_zero "int *target" "bool *z"
.Ft bool
.Fn ck_pr_dec_int_is_zero "int *target"
.Ft void .Ft void
.Fn ck_pr_dec_64 "uint64_t *target" .Fn ck_pr_dec_64 "uint64_t *target"
.Ft void .Ft void
.Fn ck_pr_dec_64_zero "uint64_t *target" "bool *z" .Fn ck_pr_dec_64_zero "uint64_t *target" "bool *z"
.Ft bool
.Fn ck_pr_dec_64_is_zero "uint64_t *target"
.Ft void .Ft void
.Fn ck_pr_dec_32 "uint32_t *target" .Fn ck_pr_dec_32 "uint32_t *target"
.Ft void .Ft void
.Fn ck_pr_dec_32_zero "uint32_t *target" "bool *z" .Fn ck_pr_dec_32_zero "uint32_t *target" "bool *z"
.Ft bool
.Fn ck_pr_dec_32_is_zero "uint32_t *target"
.Ft void .Ft void
.Fn ck_pr_dec_16 "uint16_t *target" .Fn ck_pr_dec_16 "uint16_t *target"
.Ft void .Ft void
.Fn ck_pr_dec_16_zero "uint16_t *target" "bool *z" .Fn ck_pr_dec_16_zero "uint16_t *target" "bool *z"
.Ft bool
.Fn ck_pr_dec_16_is_zero "uint16_t *target"
.Ft void .Ft void
.Fn ck_pr_dec_8 "uint8_t *target" .Fn ck_pr_dec_8 "uint8_t *target"
.Ft void .Ft void
.Fn ck_pr_dec_8_zero "uint8_t *target" "bool *z" .Fn ck_pr_dec_8_zero "uint8_t *target" "bool *z"
.Ft bool
.Fn ck_pr_dec_8_is_zero "uint8_t *target"
.Sh DESCRIPTION .Sh DESCRIPTION
The The
.Fn ck_pr_dec 3 .Fn ck_pr_dec 3
@ -99,6 +126,8 @@ to true if the result
of the decrement operation was 0. They set the value pointed to by of the decrement operation was 0. They set the value pointed to by
.Fa z .Fa z
to false otherwise. to false otherwise.
The ck_pr_dec_is_zero family of function return true if the result
of the decrement operation was 0 and false otherwise.
.Sh SEE ALSO .Sh SEE ALSO
.Xr ck_pr_fence_load 3 , .Xr ck_pr_fence_load 3 ,
.Xr ck_pr_fence_load_depends 3 , .Xr ck_pr_fence_load_depends 3 ,

@ -29,22 +29,31 @@
.Sh NAME .Sh NAME
.Nm ck_pr_inc_ptr , .Nm ck_pr_inc_ptr ,
.Nm ck_pr_inc_ptr_zero , .Nm ck_pr_inc_ptr_zero ,
.Nm ck_pr_inc_ptr_is_zero ,
.Nm ck_pr_inc_double , .Nm ck_pr_inc_double ,
.Nm ck_pr_inc_double_zero , .Nm ck_pr_inc_double_zero ,
.Nm ck_pr_inc_double_is_zero ,
.Nm ck_pr_inc_char , .Nm ck_pr_inc_char ,
.Nm ck_pr_inc_char_zero , .Nm ck_pr_inc_char_zero ,
.Nm ck_pr_inc_char_is_zero ,
.Nm ck_pr_inc_uint , .Nm ck_pr_inc_uint ,
.Nm ck_pr_inc_uint_zero , .Nm ck_pr_inc_uint_zero ,
.Nm ck_pr_inc_uint_is_zero ,
.Nm ck_pr_inc_int , .Nm ck_pr_inc_int ,
.Nm ck_pr_inc_int_zero , .Nm ck_pr_inc_int_zero ,
.Nm ck_pr_inc_int_is_zero ,
.Nm ck_pr_inc_64 , .Nm ck_pr_inc_64 ,
.Nm ck_pr_inc_64_zero , .Nm ck_pr_inc_64_zero ,
.Nm ck_pr_inc_64_is_zero ,
.Nm ck_pr_inc_32 , .Nm ck_pr_inc_32 ,
.Nm ck_pr_inc_32_zero , .Nm ck_pr_inc_32_zero ,
.Nm ck_pr_inc_32_is_zero ,
.Nm ck_pr_inc_16 , .Nm ck_pr_inc_16 ,
.Nm ck_pr_inc_16_zero , .Nm ck_pr_inc_16_zero ,
.Nm ck_pr_inc_16_is_zero ,
.Nm ck_pr_inc_8 , .Nm ck_pr_inc_8 ,
.Nm ck_pr_inc_8_zero .Nm ck_pr_inc_8_zero ,
.Nm ck_pr_inc_8_is_zero
.Nd atomic increment operations .Nd atomic increment operations
.Sh LIBRARY .Sh LIBRARY
Concurrency Kit (libck, \-lck) Concurrency Kit (libck, \-lck)
@ -54,38 +63,56 @@ Concurrency Kit (libck, \-lck)
.Fn ck_pr_inc_ptr "void *target" .Fn ck_pr_inc_ptr "void *target"
.Ft void .Ft void
.Fn ck_pr_inc_ptr_zero "void *target" "bool *z" .Fn ck_pr_inc_ptr_zero "void *target" "bool *z"
.Ft bool
.Fn ck_pr_inc_ptr_is_zero "void *target"
.Ft void .Ft void
.Fn ck_pr_inc_double "double *target" .Fn ck_pr_inc_double "double *target"
.Ft void .Ft void
.Fn ck_pr_inc_double_zero "double *target" "bool *z" .Fn ck_pr_inc_double_zero "double *target" "bool *z"
.Ft bool
.Fn ck_pr_inc_double_is_zero "double *target"
.Ft void .Ft void
.Fn ck_pr_inc_char "char *target" .Fn ck_pr_inc_char "char *target"
.Ft void .Ft void
.Fn ck_pr_inc_char_zero "char *target" "bool *z" .Fn ck_pr_inc_char_zero "char *target" "bool *z"
.Ft bool
.Fn ck_pr_inc_char_is_zero "char *target"
.Ft void .Ft void
.Fn ck_pr_inc_uint "unsigned int *target" .Fn ck_pr_inc_uint "unsigned int *target"
.Ft void .Ft void
.Fn ck_pr_inc_uint_zero "unsigned int *target" "bool *z" .Fn ck_pr_inc_uint_zero "unsigned int *target" "bool *z"
.Ft bool
.Fn ck_pr_inc_uint_is_zero "unsigned int *target"
.Ft void .Ft void
.Fn ck_pr_inc_int "int *target" .Fn ck_pr_inc_int "int *target"
.Ft void .Ft void
.Fn ck_pr_inc_int_zero "int *target" "bool *z" .Fn ck_pr_inc_int_zero "int *target" "bool *z"
.Ft bool
.Fn ck_pr_inc_int_is_zero "int *target"
.Ft void .Ft void
.Fn ck_pr_inc_64 "uint64_t *target" .Fn ck_pr_inc_64 "uint64_t *target"
.Ft void .Ft void
.Fn ck_pr_inc_64_zero "uint64_t *target" "bool *z" .Fn ck_pr_inc_64_zero "uint64_t *target" "bool *z"
.Ft bool
.Fn ck_pr_inc_64_is_zero "uint64_t *target"
.Ft void .Ft void
.Fn ck_pr_inc_32 "uint32_t *target" .Fn ck_pr_inc_32 "uint32_t *target"
.Ft void .Ft void
.Fn ck_pr_inc_32_zero "uint32_t *target" "bool *z" .Fn ck_pr_inc_32_zero "uint32_t *target" "bool *z"
.Ft bool
.Fn ck_pr_inc_32_is_zero "uint32_t *target"
.Ft void .Ft void
.Fn ck_pr_inc_16 "uint16_t *target" .Fn ck_pr_inc_16 "uint16_t *target"
.Ft void .Ft void
.Fn ck_pr_inc_16_zero "uint16_t *target" "bool *z" .Fn ck_pr_inc_16_zero "uint16_t *target" "bool *z"
.Ft bool
.Fn ck_pr_inc_16_is_zero "uint16_t *target"
.Ft void .Ft void
.Fn ck_pr_inc_8 "uint8_t *target" .Fn ck_pr_inc_8 "uint8_t *target"
.Ft void .Ft void
.Fn ck_pr_inc_8_zero "uint8_t *target" "bool *z" .Fn ck_pr_inc_8_zero "uint8_t *target" "bool *z"
.Ft bool
.Fn ck_pr_inc_8_is_zero "uint8_t *target"
.Sh DESCRIPTION .Sh DESCRIPTION
The The
.Fn ck_pr_inc 3 .Fn ck_pr_inc 3
@ -99,6 +126,8 @@ to true if the result of the increment operation was 0. The functions set
the value pointed to by the value pointed to by
.Fa z .Fa z
false otherwise. false otherwise.
The ck_pr_inc_is_zero family of function return true if the result
of the decrement operation was 0 and false otherwise.
.Sh SEE ALSO .Sh SEE ALSO
.Xr ck_pr_fence_load 3 , .Xr ck_pr_fence_load 3 ,
.Xr ck_pr_fence_load_depends 3 , .Xr ck_pr_fence_load_depends 3 ,

@ -615,8 +615,8 @@ CK_PR_BTX_S(bts, 16, uint16_t, |,)
} }
#define CK_PR_UNARY_Z(K, S, M, T, P, C, Z) \ #define CK_PR_UNARY_Z(K, S, M, T, P, C, Z) \
CK_CC_INLINE static void \ CK_CC_INLINE static bool \
ck_pr_##K##_##S##_zero(M *target, bool *zero) \ ck_pr_##K##_##S##_is_zero(M *target) \
{ \ { \
T previous; \ T previous; \
C punt; \ C punt; \
@ -627,12 +627,21 @@ CK_PR_BTX_S(bts, 16, uint16_t, |,)
(C)(previous P 1), \ (C)(previous P 1), \
&previous) == false) \ &previous) == false) \
ck_pr_stall(); \ ck_pr_stall(); \
*zero = previous == (T)Z; \ return previous == (T)Z; \
}
#define CK_PR_UNARY_Z_STUB(K, S, M) \
CK_CC_INLINE static void \
ck_pr_##K##_##S##_zero(M *target, bool *zero) \
{ \
*zero = ck_pr_##K##_##S##_is_zero(target); \
return; \ return; \
} }
#define CK_PR_UNARY_S(K, X, S, M) CK_PR_UNARY(K, X, S, M, M) #define CK_PR_UNARY_S(K, X, S, M) CK_PR_UNARY(K, X, S, M, M)
#define CK_PR_UNARY_Z_S(K, S, M, P, Z) CK_PR_UNARY_Z(K, S, M, M, P, M, Z) #define CK_PR_UNARY_Z_S(K, S, M, P, Z) \
CK_PR_UNARY_Z(K, S, M, M, P, M, Z) \
CK_PR_UNARY_Z_STUB(K, S, M)
#if defined(CK_F_PR_LOAD_CHAR) && defined(CK_F_PR_CAS_CHAR_VALUE) #if defined(CK_F_PR_LOAD_CHAR) && defined(CK_F_PR_CAS_CHAR_VALUE)
@ -644,6 +653,8 @@ CK_PR_UNARY_S(inc, add, char, char)
#ifndef CK_F_PR_INC_CHAR_ZERO #ifndef CK_F_PR_INC_CHAR_ZERO
#define CK_F_PR_INC_CHAR_ZERO #define CK_F_PR_INC_CHAR_ZERO
CK_PR_UNARY_Z_S(inc, char, char, +, -1) CK_PR_UNARY_Z_S(inc, char, char, +, -1)
#else
CK_PR_UNARY_Z_STUB(inc, char, char)
#endif /* CK_F_PR_INC_CHAR_ZERO */ #endif /* CK_F_PR_INC_CHAR_ZERO */
#ifndef CK_F_PR_DEC_CHAR #ifndef CK_F_PR_DEC_CHAR
@ -654,6 +665,8 @@ CK_PR_UNARY_S(dec, sub, char, char)
#ifndef CK_F_PR_DEC_CHAR_ZERO #ifndef CK_F_PR_DEC_CHAR_ZERO
#define CK_F_PR_DEC_CHAR_ZERO #define CK_F_PR_DEC_CHAR_ZERO
CK_PR_UNARY_Z_S(dec, char, char, -, 1) CK_PR_UNARY_Z_S(dec, char, char, -, 1)
#else
CK_PR_UNARY_Z_STUB(dec, char, char)
#endif /* CK_F_PR_DEC_CHAR_ZERO */ #endif /* CK_F_PR_DEC_CHAR_ZERO */
#endif /* CK_F_PR_LOAD_CHAR && CK_F_PR_CAS_CHAR_VALUE */ #endif /* CK_F_PR_LOAD_CHAR && CK_F_PR_CAS_CHAR_VALUE */
@ -668,6 +681,8 @@ CK_PR_UNARY_S(inc, add, int, int)
#ifndef CK_F_PR_INC_INT_ZERO #ifndef CK_F_PR_INC_INT_ZERO
#define CK_F_PR_INC_INT_ZERO #define CK_F_PR_INC_INT_ZERO
CK_PR_UNARY_Z_S(inc, int, int, +, -1) CK_PR_UNARY_Z_S(inc, int, int, +, -1)
#else
CK_PR_UNARY_Z_STUB(inc, int, int)
#endif /* CK_F_PR_INC_INT_ZERO */ #endif /* CK_F_PR_INC_INT_ZERO */
#ifndef CK_F_PR_DEC_INT #ifndef CK_F_PR_DEC_INT
@ -678,6 +693,8 @@ CK_PR_UNARY_S(dec, sub, int, int)
#ifndef CK_F_PR_DEC_INT_ZERO #ifndef CK_F_PR_DEC_INT_ZERO
#define CK_F_PR_DEC_INT_ZERO #define CK_F_PR_DEC_INT_ZERO
CK_PR_UNARY_Z_S(dec, int, int, -, 1) CK_PR_UNARY_Z_S(dec, int, int, -, 1)
#else
CK_PR_UNARY_Z_STUB(dec, int, int)
#endif /* CK_F_PR_DEC_INT_ZERO */ #endif /* CK_F_PR_DEC_INT_ZERO */
#endif /* CK_F_PR_LOAD_INT && CK_F_PR_CAS_INT_VALUE */ #endif /* CK_F_PR_LOAD_INT && CK_F_PR_CAS_INT_VALUE */
@ -707,6 +724,8 @@ CK_PR_UNARY_S(inc, add, uint, unsigned int)
#ifndef CK_F_PR_INC_UINT_ZERO #ifndef CK_F_PR_INC_UINT_ZERO
#define CK_F_PR_INC_UINT_ZERO #define CK_F_PR_INC_UINT_ZERO
CK_PR_UNARY_Z_S(inc, uint, unsigned int, +, UINT_MAX) CK_PR_UNARY_Z_S(inc, uint, unsigned int, +, UINT_MAX)
#else
CK_PR_UNARY_Z_STUB(inc, uint, unsigned int)
#endif /* CK_F_PR_INC_UINT_ZERO */ #endif /* CK_F_PR_INC_UINT_ZERO */
#ifndef CK_F_PR_DEC_UINT #ifndef CK_F_PR_DEC_UINT
@ -717,6 +736,8 @@ CK_PR_UNARY_S(dec, sub, uint, unsigned int)
#ifndef CK_F_PR_DEC_UINT_ZERO #ifndef CK_F_PR_DEC_UINT_ZERO
#define CK_F_PR_DEC_UINT_ZERO #define CK_F_PR_DEC_UINT_ZERO
CK_PR_UNARY_Z_S(dec, uint, unsigned int, -, 1) CK_PR_UNARY_Z_S(dec, uint, unsigned int, -, 1)
#else
CK_PR_UNARY_Z_STUB(dec, uint, unsigned int)
#endif /* CK_F_PR_DEC_UINT_ZERO */ #endif /* CK_F_PR_DEC_UINT_ZERO */
#endif /* CK_F_PR_LOAD_UINT && CK_F_PR_CAS_UINT_VALUE */ #endif /* CK_F_PR_LOAD_UINT && CK_F_PR_CAS_UINT_VALUE */
@ -731,6 +752,8 @@ CK_PR_UNARY(inc, add, ptr, void, uintptr_t)
#ifndef CK_F_PR_INC_PTR_ZERO #ifndef CK_F_PR_INC_PTR_ZERO
#define CK_F_PR_INC_PTR_ZERO #define CK_F_PR_INC_PTR_ZERO
CK_PR_UNARY_Z(inc, ptr, void, uintptr_t, +, void *, UINT_MAX) CK_PR_UNARY_Z(inc, ptr, void, uintptr_t, +, void *, UINT_MAX)
#else
CK_PR_UNARY_Z_STUB(inc, ptr, void)
#endif /* CK_F_PR_INC_PTR_ZERO */ #endif /* CK_F_PR_INC_PTR_ZERO */
#ifndef CK_F_PR_DEC_PTR #ifndef CK_F_PR_DEC_PTR
@ -741,6 +764,8 @@ CK_PR_UNARY(dec, sub, ptr, void, uintptr_t)
#ifndef CK_F_PR_DEC_PTR_ZERO #ifndef CK_F_PR_DEC_PTR_ZERO
#define CK_F_PR_DEC_PTR_ZERO #define CK_F_PR_DEC_PTR_ZERO
CK_PR_UNARY_Z(dec, ptr, void, uintptr_t, -, void *, 1) CK_PR_UNARY_Z(dec, ptr, void, uintptr_t, -, void *, 1)
#else
CK_PR_UNARY_Z_STUB(dec, ptr, void)
#endif /* CK_F_PR_DEC_PTR_ZERO */ #endif /* CK_F_PR_DEC_PTR_ZERO */
#endif /* CK_F_PR_LOAD_PTR && CK_F_PR_CAS_PTR_VALUE */ #endif /* CK_F_PR_LOAD_PTR && CK_F_PR_CAS_PTR_VALUE */
@ -755,6 +780,8 @@ CK_PR_UNARY_S(inc, add, 64, uint64_t)
#ifndef CK_F_PR_INC_64_ZERO #ifndef CK_F_PR_INC_64_ZERO
#define CK_F_PR_INC_64_ZERO #define CK_F_PR_INC_64_ZERO
CK_PR_UNARY_Z_S(inc, 64, uint64_t, +, UINT64_MAX) CK_PR_UNARY_Z_S(inc, 64, uint64_t, +, UINT64_MAX)
#else
CK_PR_UNARY_Z_STUB(inc, 64, uint64_t)
#endif /* CK_F_PR_INC_64_ZERO */ #endif /* CK_F_PR_INC_64_ZERO */
#ifndef CK_F_PR_DEC_64 #ifndef CK_F_PR_DEC_64
@ -765,6 +792,8 @@ CK_PR_UNARY_S(dec, sub, 64, uint64_t)
#ifndef CK_F_PR_DEC_64_ZERO #ifndef CK_F_PR_DEC_64_ZERO
#define CK_F_PR_DEC_64_ZERO #define CK_F_PR_DEC_64_ZERO
CK_PR_UNARY_Z_S(dec, 64, uint64_t, -, 1) CK_PR_UNARY_Z_S(dec, 64, uint64_t, -, 1)
#else
CK_PR_UNARY_Z_STUB(dec, 64, uint64_t)
#endif /* CK_F_PR_DEC_64_ZERO */ #endif /* CK_F_PR_DEC_64_ZERO */
#endif /* CK_F_PR_LOAD_64 && CK_F_PR_CAS_64_VALUE */ #endif /* CK_F_PR_LOAD_64 && CK_F_PR_CAS_64_VALUE */
@ -779,6 +808,8 @@ CK_PR_UNARY_S(inc, add, 32, uint32_t)
#ifndef CK_F_PR_INC_32_ZERO #ifndef CK_F_PR_INC_32_ZERO
#define CK_F_PR_INC_32_ZERO #define CK_F_PR_INC_32_ZERO
CK_PR_UNARY_Z_S(inc, 32, uint32_t, +, UINT32_MAX) CK_PR_UNARY_Z_S(inc, 32, uint32_t, +, UINT32_MAX)
#else
CK_PR_UNARY_Z_STUB(inc, 32, uint32_t)
#endif /* CK_F_PR_INC_32_ZERO */ #endif /* CK_F_PR_INC_32_ZERO */
#ifndef CK_F_PR_DEC_32 #ifndef CK_F_PR_DEC_32
@ -789,6 +820,8 @@ CK_PR_UNARY_S(dec, sub, 32, uint32_t)
#ifndef CK_F_PR_DEC_32_ZERO #ifndef CK_F_PR_DEC_32_ZERO
#define CK_F_PR_DEC_32_ZERO #define CK_F_PR_DEC_32_ZERO
CK_PR_UNARY_Z_S(dec, 32, uint32_t, -, 1) CK_PR_UNARY_Z_S(dec, 32, uint32_t, -, 1)
#else
CK_PR_UNARY_Z_STUB(dec, 32, uint32_t)
#endif /* CK_F_PR_DEC_32_ZERO */ #endif /* CK_F_PR_DEC_32_ZERO */
#endif /* CK_F_PR_LOAD_32 && CK_F_PR_CAS_32_VALUE */ #endif /* CK_F_PR_LOAD_32 && CK_F_PR_CAS_32_VALUE */
@ -803,6 +836,8 @@ CK_PR_UNARY_S(inc, add, 16, uint16_t)
#ifndef CK_F_PR_INC_16_ZERO #ifndef CK_F_PR_INC_16_ZERO
#define CK_F_PR_INC_16_ZERO #define CK_F_PR_INC_16_ZERO
CK_PR_UNARY_Z_S(inc, 16, uint16_t, +, UINT16_MAX) CK_PR_UNARY_Z_S(inc, 16, uint16_t, +, UINT16_MAX)
#else
CK_PR_UNARY_Z_STUB(inc, 16, uint16_t)
#endif /* CK_F_PR_INC_16_ZERO */ #endif /* CK_F_PR_INC_16_ZERO */
#ifndef CK_F_PR_DEC_16 #ifndef CK_F_PR_DEC_16
@ -813,6 +848,8 @@ CK_PR_UNARY_S(dec, sub, 16, uint16_t)
#ifndef CK_F_PR_DEC_16_ZERO #ifndef CK_F_PR_DEC_16_ZERO
#define CK_F_PR_DEC_16_ZERO #define CK_F_PR_DEC_16_ZERO
CK_PR_UNARY_Z_S(dec, 16, uint16_t, -, 1) CK_PR_UNARY_Z_S(dec, 16, uint16_t, -, 1)
#else
CK_PR_UNARY_Z_STUB(dec, 16, uint16_t)
#endif /* CK_F_PR_DEC_16_ZERO */ #endif /* CK_F_PR_DEC_16_ZERO */
#endif /* CK_F_PR_LOAD_16 && CK_F_PR_CAS_16_VALUE */ #endif /* CK_F_PR_LOAD_16 && CK_F_PR_CAS_16_VALUE */
@ -827,6 +864,8 @@ CK_PR_UNARY_S(inc, add, 8, uint8_t)
#ifndef CK_F_PR_INC_8_ZERO #ifndef CK_F_PR_INC_8_ZERO
#define CK_F_PR_INC_8_ZERO #define CK_F_PR_INC_8_ZERO
CK_PR_UNARY_Z_S(inc, 8, uint8_t, +, UINT8_MAX) CK_PR_UNARY_Z_S(inc, 8, uint8_t, +, UINT8_MAX)
#else
CK_PR_UNARY_Z_STUB(inc, 8, uint8_t)
#endif /* CK_F_PR_INC_8_ZERO */ #endif /* CK_F_PR_INC_8_ZERO */
#ifndef CK_F_PR_DEC_8 #ifndef CK_F_PR_DEC_8
@ -837,6 +876,8 @@ CK_PR_UNARY_S(dec, sub, 8, uint8_t)
#ifndef CK_F_PR_DEC_8_ZERO #ifndef CK_F_PR_DEC_8_ZERO
#define CK_F_PR_DEC_8_ZERO #define CK_F_PR_DEC_8_ZERO
CK_PR_UNARY_Z_S(dec, 8, uint8_t, -, 1) CK_PR_UNARY_Z_S(dec, 8, uint8_t, -, 1)
#else
CK_PR_UNARY_Z_STUB(dec, 8, uint8_t)
#endif /* CK_F_PR_DEC_8_ZERO */ #endif /* CK_F_PR_DEC_8_ZERO */
#endif /* CK_F_PR_LOAD_8 && CK_F_PR_CAS_8_VALUE */ #endif /* CK_F_PR_LOAD_8 && CK_F_PR_CAS_8_VALUE */

@ -233,18 +233,18 @@ CK_PR_FAA_S(8, uint8_t, "xaddb")
} }
#define CK_PR_UNARY_V(K, S, T, C, I) \ #define CK_PR_UNARY_V(K, S, T, C, I) \
CK_CC_INLINE static void \ CK_CC_INLINE static bool \
ck_pr_##K##_##S##_zero(T *target, bool *r) \ ck_pr_##K##_##S##_is_zero(T *target) \
{ \ { \
bool ret; \
__asm__ __volatile__(CK_PR_LOCK_PREFIX I " %0; setz %1" \ __asm__ __volatile__(CK_PR_LOCK_PREFIX I " %0; setz %1" \
: "+m" (*(C *)target), \ : "+m" (*(C *)target), \
"=m" (*r) \ "=rm" (ret) \
: \ : \
: "memory", "cc"); \ : "memory", "cc"); \
return; \ return ret; \
} }
#define CK_PR_UNARY_S(K, S, T, I) CK_PR_UNARY(K, S, T, T, I) #define CK_PR_UNARY_S(K, S, T, I) CK_PR_UNARY(K, S, T, T, I)
#define CK_PR_GENERATE(K) \ #define CK_PR_GENERATE(K) \

@ -332,18 +332,18 @@ CK_PR_FAA_S(8, uint8_t, "xaddb")
} }
#define CK_PR_UNARY_V(K, S, T, C, I) \ #define CK_PR_UNARY_V(K, S, T, C, I) \
CK_CC_INLINE static void \ CK_CC_INLINE static bool \
ck_pr_##K##_##S##_zero(T *target, bool *r) \ ck_pr_##K##_##S##_is_zero(T *target) \
{ \ { \
bool ret; \
__asm__ __volatile__(CK_PR_LOCK_PREFIX I " %0; setz %1" \ __asm__ __volatile__(CK_PR_LOCK_PREFIX I " %0; setz %1" \
: "+m" (*(C *)target), \ : "+m" (*(C *)target), \
"=m" (*r) \ "=rm" (ret) \
: \ : \
: "memory", "cc"); \ : "memory", "cc"); \
return; \ return ret; \
} }
#define CK_PR_UNARY_S(K, S, T, I) CK_PR_UNARY(K, S, T, T, I) #define CK_PR_UNARY_S(K, S, T, I) CK_PR_UNARY(K, S, T, T, I)
#define CK_PR_GENERATE(K) \ #define CK_PR_GENERATE(K) \

@ -4,7 +4,7 @@ OBJECTS=ck_pr_cas ck_pr_faa ck_pr_inc ck_pr_dec ck_pr_bts \
ck_pr_btr ck_pr_btc ck_pr_load ck_pr_store \ ck_pr_btr ck_pr_btc ck_pr_load ck_pr_store \
ck_pr_and ck_pr_or ck_pr_xor ck_pr_add ck_pr_sub \ ck_pr_and ck_pr_or ck_pr_xor ck_pr_add ck_pr_sub \
ck_pr_fas ck_pr_bin ck_pr_btx ck_pr_fax ck_pr_n \ ck_pr_fas ck_pr_bin ck_pr_btx ck_pr_fax ck_pr_n \
ck_pr_unary ck_pr_fence ck_pr_unary ck_pr_fence ck_pr_dec_zero ck_pr_inc_zero
all: $(OBJECTS) all: $(OBJECTS)
@ -20,9 +20,15 @@ ck_pr_cas: ck_pr_cas.c
ck_pr_inc: ck_pr_inc.c ck_pr_inc: ck_pr_inc.c
$(CC) $(CFLAGS) -o ck_pr_inc ck_pr_inc.c $(CC) $(CFLAGS) -o ck_pr_inc ck_pr_inc.c
ck_pr_inc_zero: ck_pr_inc_zero.c
$(CC) $(CFLAGS) -o ck_pr_inc_zero ck_pr_inc_zero.c
ck_pr_dec: ck_pr_dec.c ck_pr_dec: ck_pr_dec.c
$(CC) $(CFLAGS) -o ck_pr_dec ck_pr_dec.c $(CC) $(CFLAGS) -o ck_pr_dec ck_pr_dec.c
ck_pr_dec_zero: ck_pr_dec_zero.c
$(CC) $(CFLAGS) -o ck_pr_dec_zero ck_pr_dec_zero.c
ck_pr_faa: ck_pr_faa.c ck_pr_faa: ck_pr_faa.c
$(CC) $(CFLAGS) -o ck_pr_faa ck_pr_faa.c $(CC) $(CFLAGS) -o ck_pr_faa ck_pr_faa.c

@ -0,0 +1,105 @@
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <ck_pr.h>
#define EXPECT(ACTUAL, IS_ZERO, TYPE, INITIAL) do { \
TYPE expected = (TYPE)((TYPE)INITIAL - (TYPE)1); \
if ((ACTUAL) != expected) { \
printf("FAIL [ %" PRIx64" != %" PRIx64" ]\n", \
(uint64_t)(ACTUAL), \
(uint64_t)expected); \
exit(EXIT_FAILURE); \
} \
\
if ((IS_ZERO) != ((ACTUAL) == 0)) { \
printf("FAIL [ %s != %s ]\n", \
((IS_ZERO) ? "true" : "false"), \
(((ACTUAL) == 0) ? "true" : "false")); \
exit(EXIT_FAILURE); \
} \
} while (0)
#define TEST_ZERO(TYPE, SUFFIX) do { \
TYPE datum; \
bool is_zero; \
\
datum = 0; \
ck_pr_dec_##SUFFIX##_zero(&datum, &is_zero); \
EXPECT(datum, is_zero, TYPE, 0); \
\
datum = (TYPE)-1; \
ck_pr_dec_##SUFFIX##_zero(&datum, &is_zero); \
EXPECT(datum, is_zero, TYPE, -1); \
\
datum = (TYPE)1; \
ck_pr_dec_##SUFFIX##_zero(&datum, &is_zero); \
EXPECT(datum, is_zero, TYPE, 1); \
\
datum = (TYPE)2; \
ck_pr_dec_##SUFFIX##_zero(&datum, &is_zero); \
EXPECT(datum, is_zero, TYPE, 2); \
} while (0)
#define TEST_IS_ZERO(TYPE, SUFFIX) do { \
TYPE datum; \
bool is_zero; \
\
datum = 0; \
is_zero = ck_pr_dec_##SUFFIX##_is_zero(&datum); \
EXPECT(datum, is_zero, TYPE, 0); \
\
datum = (TYPE)-1; \
is_zero = ck_pr_dec_##SUFFIX##_is_zero(&datum); \
EXPECT(datum, is_zero, TYPE, -1); \
\
datum = (TYPE)1; \
is_zero = ck_pr_dec_##SUFFIX##_is_zero(&datum); \
EXPECT(datum, is_zero, TYPE, 1); \
\
datum = (TYPE)2; \
is_zero = ck_pr_dec_##SUFFIX##_is_zero(&datum); \
EXPECT(datum, is_zero, TYPE, 2); \
} while (0)
#define TEST(TYPE, SUFFIX) do { \
TEST_ZERO(TYPE, SUFFIX); \
TEST_IS_ZERO(TYPE, SUFFIX); \
} while (0)
int
main(void)
{
#ifdef CK_F_PR_DEC_64_ZERO
TEST(uint64_t, 64);
#endif
#ifdef CK_F_PR_DEC_32_ZERO
TEST(uint32_t, 32);
#endif
#ifdef CK_F_PR_DEC_16_ZERO
TEST(uint16_t, 16);
#endif
#ifdef CK_F_PR_DEC_8_ZERO
TEST(uint8_t, 8);
#endif
#ifdef CK_F_PR_DEC_UINT_ZERO
TEST(unsigned int, uint);
#endif
#ifdef CK_F_PR_DEC_INT_ZERO
TEST(int, int);
#endif
#ifdef CK_F_PR_DEC_CHAR_ZERO
TEST(char, char);
#endif
return (0);
}

@ -0,0 +1,105 @@
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <ck_pr.h>
#define EXPECT(ACTUAL, IS_ZERO, TYPE, INITIAL) do { \
TYPE expected = (TYPE)((TYPE)INITIAL + (TYPE)1); \
if ((ACTUAL) != expected) { \
printf("FAIL [ %" PRIx64" != %" PRIx64" ]\n", \
(uint64_t)(ACTUAL), \
(uint64_t)expected); \
exit(EXIT_FAILURE); \
} \
\
if ((IS_ZERO) != ((ACTUAL) == 0)) { \
printf("FAIL [ %s != %s ]\n", \
((IS_ZERO) ? "true" : "false"), \
(((ACTUAL) == 0) ? "true" : "false")); \
exit(EXIT_FAILURE); \
} \
} while (0)
#define TEST_ZERO(TYPE, SUFFIX) do { \
TYPE datum; \
bool is_zero; \
\
datum = 0; \
ck_pr_inc_##SUFFIX##_zero(&datum, &is_zero); \
EXPECT(datum, is_zero, TYPE, 0); \
\
datum = (TYPE)-1; \
ck_pr_inc_##SUFFIX##_zero(&datum, &is_zero); \
EXPECT(datum, is_zero, TYPE, -1); \
\
datum = (TYPE)1; \
ck_pr_inc_##SUFFIX##_zero(&datum, &is_zero); \
EXPECT(datum, is_zero, TYPE, 1); \
\
datum = (TYPE)2; \
ck_pr_inc_##SUFFIX##_zero(&datum, &is_zero); \
EXPECT(datum, is_zero, TYPE, 2); \
} while (0)
#define TEST_IS_ZERO(TYPE, SUFFIX) do { \
TYPE datum; \
bool is_zero; \
\
datum = 0; \
is_zero = ck_pr_inc_##SUFFIX##_is_zero(&datum); \
EXPECT(datum, is_zero, TYPE, 0); \
\
datum = (TYPE)-1; \
is_zero = ck_pr_inc_##SUFFIX##_is_zero(&datum); \
EXPECT(datum, is_zero, TYPE, -1); \
\
datum = (TYPE)1; \
is_zero = ck_pr_inc_##SUFFIX##_is_zero(&datum); \
EXPECT(datum, is_zero, TYPE, 1); \
\
datum = (TYPE)2; \
is_zero = ck_pr_inc_##SUFFIX##_is_zero(&datum); \
EXPECT(datum, is_zero, TYPE, 2); \
} while (0)
#define TEST(TYPE, SUFFIX) do { \
TEST_ZERO(TYPE, SUFFIX); \
TEST_IS_ZERO(TYPE, SUFFIX); \
} while (0)
int
main(void)
{
#ifdef CK_F_PR_INC_64_ZERO
TEST(uint64_t, 64);
#endif
#ifdef CK_F_PR_INC_32_ZERO
TEST(uint32_t, 32);
#endif
#ifdef CK_F_PR_INC_16_ZERO
TEST(uint16_t, 16);
#endif
#ifdef CK_F_PR_INC_8_ZERO
TEST(uint8_t, 8);
#endif
#ifdef CK_F_PR_INC_UINT_ZERO
TEST(unsigned int, uint);
#endif
#ifdef CK_F_PR_INC_INT_ZERO
TEST(int, int);
#endif
#ifdef CK_F_PR_INC_CHAR_ZERO
TEST(char, char);
#endif
return (0);
}
Loading…
Cancel
Save