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
.Nm ck_pr_dec_ptr ,
.Nm ck_pr_dec_ptr_zero ,
.Nm ck_pr_dec_ptr_is_zero ,
.Nm ck_pr_dec_double ,
.Nm ck_pr_dec_double_zero ,
.Nm ck_pr_dec_double_is_zero ,
.Nm ck_pr_dec_char ,
.Nm ck_pr_dec_char_zero ,
.Nm ck_pr_dec_char_is_zero ,
.Nm ck_pr_dec_uint ,
.Nm ck_pr_dec_uint_zero ,
.Nm ck_pr_dec_char_is_zero ,
.Nm ck_pr_dec_int ,
.Nm ck_pr_dec_int_zero ,
.Nm ck_pr_dec_int_is_zero ,
.Nm ck_pr_dec_64 ,
.Nm ck_pr_dec_64_zero ,
.Nm ck_pr_dec_64_is_zero ,
.Nm ck_pr_dec_32 ,
.Nm ck_pr_dec_32_zero ,
.Nm ck_pr_dec_32_is_zero ,
.Nm ck_pr_dec_16 ,
.Nm ck_pr_dec_16_zero ,
.Nm ck_pr_dec_32_is_zero ,
.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
.Sh LIBRARY
Concurrency Kit (libck, \-lck)
@ -54,38 +63,56 @@ Concurrency Kit (libck, \-lck)
.Fn ck_pr_dec_ptr "void *target"
.Ft void
.Fn ck_pr_dec_ptr_zero "void *target" "bool *z"
.Ft bool
.Fn ck_pr_dec_ptr_is_zero "void *target"
.Ft void
.Fn ck_pr_dec_double "double *target"
.Ft void
.Fn ck_pr_dec_double_zero "double *target" "bool *z"
.Ft bool
.Fn ck_pr_dec_double_is_zero "double *target"
.Ft void
.Fn ck_pr_dec_char "char *target"
.Ft void
.Fn ck_pr_dec_char_zero "char *target" "bool *z"
.Ft bool
.Fn ck_pr_dec_char_is_zero "char *target"
.Ft void
.Fn ck_pr_dec_uint "unsigned int *target"
.Ft void
.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
.Fn ck_pr_dec_int "int *target"
.Ft void
.Fn ck_pr_dec_int_zero "int *target" "bool *z"
.Ft bool
.Fn ck_pr_dec_int_is_zero "int *target"
.Ft void
.Fn ck_pr_dec_64 "uint64_t *target"
.Ft void
.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
.Fn ck_pr_dec_32 "uint32_t *target"
.Ft void
.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
.Fn ck_pr_dec_16 "uint16_t *target"
.Ft void
.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
.Fn ck_pr_dec_8 "uint8_t *target"
.Ft void
.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
The
.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
.Fa z
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
.Xr ck_pr_fence_load 3 ,
.Xr ck_pr_fence_load_depends 3 ,

@ -29,22 +29,31 @@
.Sh NAME
.Nm ck_pr_inc_ptr ,
.Nm ck_pr_inc_ptr_zero ,
.Nm ck_pr_inc_ptr_is_zero ,
.Nm ck_pr_inc_double ,
.Nm ck_pr_inc_double_zero ,
.Nm ck_pr_inc_double_is_zero ,
.Nm ck_pr_inc_char ,
.Nm ck_pr_inc_char_zero ,
.Nm ck_pr_inc_char_is_zero ,
.Nm ck_pr_inc_uint ,
.Nm ck_pr_inc_uint_zero ,
.Nm ck_pr_inc_uint_is_zero ,
.Nm ck_pr_inc_int ,
.Nm ck_pr_inc_int_zero ,
.Nm ck_pr_inc_int_is_zero ,
.Nm ck_pr_inc_64 ,
.Nm ck_pr_inc_64_zero ,
.Nm ck_pr_inc_64_is_zero ,
.Nm ck_pr_inc_32 ,
.Nm ck_pr_inc_32_zero ,
.Nm ck_pr_inc_32_is_zero ,
.Nm ck_pr_inc_16 ,
.Nm ck_pr_inc_16_zero ,
.Nm ck_pr_inc_16_is_zero ,
.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
.Sh LIBRARY
Concurrency Kit (libck, \-lck)
@ -54,38 +63,56 @@ Concurrency Kit (libck, \-lck)
.Fn ck_pr_inc_ptr "void *target"
.Ft void
.Fn ck_pr_inc_ptr_zero "void *target" "bool *z"
.Ft bool
.Fn ck_pr_inc_ptr_is_zero "void *target"
.Ft void
.Fn ck_pr_inc_double "double *target"
.Ft void
.Fn ck_pr_inc_double_zero "double *target" "bool *z"
.Ft bool
.Fn ck_pr_inc_double_is_zero "double *target"
.Ft void
.Fn ck_pr_inc_char "char *target"
.Ft void
.Fn ck_pr_inc_char_zero "char *target" "bool *z"
.Ft bool
.Fn ck_pr_inc_char_is_zero "char *target"
.Ft void
.Fn ck_pr_inc_uint "unsigned int *target"
.Ft void
.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
.Fn ck_pr_inc_int "int *target"
.Ft void
.Fn ck_pr_inc_int_zero "int *target" "bool *z"
.Ft bool
.Fn ck_pr_inc_int_is_zero "int *target"
.Ft void
.Fn ck_pr_inc_64 "uint64_t *target"
.Ft void
.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
.Fn ck_pr_inc_32 "uint32_t *target"
.Ft void
.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
.Fn ck_pr_inc_16 "uint16_t *target"
.Ft void
.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
.Fn ck_pr_inc_8 "uint8_t *target"
.Ft void
.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
The
.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
.Fa z
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
.Xr ck_pr_fence_load 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) \
CK_CC_INLINE static void \
ck_pr_##K##_##S##_zero(M *target, bool *zero) \
CK_CC_INLINE static bool \
ck_pr_##K##_##S##_is_zero(M *target) \
{ \
T previous; \
C punt; \
@ -627,12 +627,21 @@ CK_PR_BTX_S(bts, 16, uint16_t, |,)
(C)(previous P 1), \
&previous) == false) \
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; \
}
#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)
@ -644,6 +653,8 @@ CK_PR_UNARY_S(inc, add, char, char)
#ifndef CK_F_PR_INC_CHAR_ZERO
#define CK_F_PR_INC_CHAR_ZERO
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 */
#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
#define CK_F_PR_DEC_CHAR_ZERO
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_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
#define CK_F_PR_INC_INT_ZERO
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 */
#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
#define CK_F_PR_DEC_INT_ZERO
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_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
#define CK_F_PR_INC_UINT_ZERO
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 */
#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
#define CK_F_PR_DEC_UINT_ZERO
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_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
#define CK_F_PR_INC_PTR_ZERO
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 */
#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
#define CK_F_PR_DEC_PTR_ZERO
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_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
#define CK_F_PR_INC_64_ZERO
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 */
#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
#define CK_F_PR_DEC_64_ZERO
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_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
#define CK_F_PR_INC_32_ZERO
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 */
#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
#define CK_F_PR_DEC_32_ZERO
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_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
#define CK_F_PR_INC_16_ZERO
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 */
#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
#define CK_F_PR_DEC_16_ZERO
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_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
#define CK_F_PR_INC_8_ZERO
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 */
#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
#define CK_F_PR_DEC_8_ZERO
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_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) \
CK_CC_INLINE static void \
ck_pr_##K##_##S##_zero(T *target, bool *r) \
CK_CC_INLINE static bool \
ck_pr_##K##_##S##_is_zero(T *target) \
{ \
bool ret; \
__asm__ __volatile__(CK_PR_LOCK_PREFIX I " %0; setz %1" \
: "+m" (*(C *)target), \
"=m" (*r) \
"=rm" (ret) \
: \
: "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_GENERATE(K) \

@ -332,18 +332,18 @@ CK_PR_FAA_S(8, uint8_t, "xaddb")
}
#define CK_PR_UNARY_V(K, S, T, C, I) \
CK_CC_INLINE static void \
ck_pr_##K##_##S##_zero(T *target, bool *r) \
CK_CC_INLINE static bool \
ck_pr_##K##_##S##_is_zero(T *target) \
{ \
bool ret; \
__asm__ __volatile__(CK_PR_LOCK_PREFIX I " %0; setz %1" \
: "+m" (*(C *)target), \
"=m" (*r) \
"=rm" (ret) \
: \
: "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_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_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_unary ck_pr_fence
ck_pr_unary ck_pr_fence ck_pr_dec_zero ck_pr_inc_zero
all: $(OBJECTS)
@ -20,9 +20,15 @@ ck_pr_cas: ck_pr_cas.c
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
$(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
$(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