From 1c2469358e46f9d6b68ddbef269c674858d802aa Mon Sep 17 00:00:00 2001 From: Theo Schlossnagle Date: Thu, 28 Jun 2018 10:34:43 -0400 Subject: [PATCH] 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 --- doc/ck_pr_dec | 31 +++++- doc/ck_pr_inc | 31 +++++- include/ck_pr.h | 49 ++++++++- include/gcc/x86/ck_pr.h | 10 +- include/gcc/x86_64/ck_pr.h | 10 +- regressions/ck_pr/validate/Makefile | 8 +- regressions/ck_pr/validate/ck_pr_dec_zero.c | 105 ++++++++++++++++++++ regressions/ck_pr/validate/ck_pr_inc_zero.c | 105 ++++++++++++++++++++ 8 files changed, 332 insertions(+), 17 deletions(-) create mode 100644 regressions/ck_pr/validate/ck_pr_dec_zero.c create mode 100644 regressions/ck_pr/validate/ck_pr_inc_zero.c diff --git a/doc/ck_pr_dec b/doc/ck_pr_dec index f3d34dd..b33ec19 100644 --- a/doc/ck_pr_dec +++ b/doc/ck_pr_dec @@ -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 , diff --git a/doc/ck_pr_inc b/doc/ck_pr_inc index 72a3e70..337e488 100644 --- a/doc/ck_pr_inc +++ b/doc/ck_pr_inc @@ -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 , diff --git a/include/ck_pr.h b/include/ck_pr.h index 4fdbdff..2de6e13 100644 --- a/include/ck_pr.h +++ b/include/ck_pr.h @@ -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 */ diff --git a/include/gcc/x86/ck_pr.h b/include/gcc/x86/ck_pr.h index 3e36376..e678e83 100644 --- a/include/gcc/x86/ck_pr.h +++ b/include/gcc/x86/ck_pr.h @@ -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) \ diff --git a/include/gcc/x86_64/ck_pr.h b/include/gcc/x86_64/ck_pr.h index 4de1332..fb2804e 100644 --- a/include/gcc/x86_64/ck_pr.h +++ b/include/gcc/x86_64/ck_pr.h @@ -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) \ diff --git a/regressions/ck_pr/validate/Makefile b/regressions/ck_pr/validate/Makefile index b19d1b5..11f1b8d 100644 --- a/regressions/ck_pr/validate/Makefile +++ b/regressions/ck_pr/validate/Makefile @@ -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 diff --git a/regressions/ck_pr/validate/ck_pr_dec_zero.c b/regressions/ck_pr/validate/ck_pr_dec_zero.c new file mode 100644 index 0000000..0f3e85f --- /dev/null +++ b/regressions/ck_pr/validate/ck_pr_dec_zero.c @@ -0,0 +1,105 @@ +#include +#include +#include +#include + +#include + +#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); +} diff --git a/regressions/ck_pr/validate/ck_pr_inc_zero.c b/regressions/ck_pr/validate/ck_pr_inc_zero.c new file mode 100644 index 0000000..e74ffba --- /dev/null +++ b/regressions/ck_pr/validate/ck_pr_inc_zero.c @@ -0,0 +1,105 @@ +#include +#include +#include +#include + +#include + +#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); +}