| #include "test/jemalloc_test.h" |
| |
| #define TEST_STRUCT(p, t) \ |
| struct p##_test_s { \ |
| t accum0; \ |
| t x; \ |
| t s; \ |
| }; \ |
| typedef struct p##_test_s p##_test_t; |
| |
| #define TEST_BODY(p, t, tc, ta, FMT) do { \ |
| const p##_test_t tests[] = { \ |
| {(t)-1, (t)-1, (t)-2}, \ |
| {(t)-1, (t) 0, (t)-2}, \ |
| {(t)-1, (t) 1, (t)-2}, \ |
| \ |
| {(t) 0, (t)-1, (t)-2}, \ |
| {(t) 0, (t) 0, (t)-2}, \ |
| {(t) 0, (t) 1, (t)-2}, \ |
| \ |
| {(t) 1, (t)-1, (t)-2}, \ |
| {(t) 1, (t) 0, (t)-2}, \ |
| {(t) 1, (t) 1, (t)-2}, \ |
| \ |
| {(t)0, (t)-(1 << 22), (t)-2}, \ |
| {(t)0, (t)(1 << 22), (t)-2}, \ |
| {(t)(1 << 22), (t)-(1 << 22), (t)-2}, \ |
| {(t)(1 << 22), (t)(1 << 22), (t)-2} \ |
| }; \ |
| unsigned i; \ |
| \ |
| for (i = 0; i < sizeof(tests)/sizeof(p##_test_t); i++) { \ |
| bool err; \ |
| t accum = tests[i].accum0; \ |
| assert_##ta##_eq(atomic_read_##p(&accum), \ |
| tests[i].accum0, \ |
| "Erroneous read, i=%u", i); \ |
| \ |
| assert_##ta##_eq(atomic_add_##p(&accum, tests[i].x), \ |
| (t)((tc)tests[i].accum0 + (tc)tests[i].x), \ |
| "i=%u, accum=%"FMT", x=%"FMT, \ |
| i, tests[i].accum0, tests[i].x); \ |
| assert_##ta##_eq(atomic_read_##p(&accum), accum, \ |
| "Erroneous add, i=%u", i); \ |
| \ |
| accum = tests[i].accum0; \ |
| assert_##ta##_eq(atomic_sub_##p(&accum, tests[i].x), \ |
| (t)((tc)tests[i].accum0 - (tc)tests[i].x), \ |
| "i=%u, accum=%"FMT", x=%"FMT, \ |
| i, tests[i].accum0, tests[i].x); \ |
| assert_##ta##_eq(atomic_read_##p(&accum), accum, \ |
| "Erroneous sub, i=%u", i); \ |
| \ |
| accum = tests[i].accum0; \ |
| err = atomic_cas_##p(&accum, tests[i].x, tests[i].s); \ |
| assert_b_eq(err, tests[i].accum0 != tests[i].x, \ |
| "Erroneous cas success/failure result"); \ |
| assert_##ta##_eq(accum, err ? tests[i].accum0 : \ |
| tests[i].s, "Erroneous cas effect, i=%u", i); \ |
| \ |
| accum = tests[i].accum0; \ |
| atomic_write_##p(&accum, tests[i].s); \ |
| assert_##ta##_eq(accum, tests[i].s, \ |
| "Erroneous write, i=%u", i); \ |
| } \ |
| } while (0) |
| |
| TEST_STRUCT(uint64, uint64_t) |
| TEST_BEGIN(test_atomic_uint64) |
| { |
| |
| #if !(LG_SIZEOF_PTR == 3 || LG_SIZEOF_INT == 3) |
| test_skip("64-bit atomic operations not supported"); |
| #else |
| TEST_BODY(uint64, uint64_t, uint64_t, u64, FMTx64); |
| #endif |
| } |
| TEST_END |
| |
| TEST_STRUCT(uint32, uint32_t) |
| TEST_BEGIN(test_atomic_uint32) |
| { |
| |
| TEST_BODY(uint32, uint32_t, uint32_t, u32, "#"FMTx32); |
| } |
| TEST_END |
| |
| TEST_STRUCT(p, void *) |
| TEST_BEGIN(test_atomic_p) |
| { |
| |
| TEST_BODY(p, void *, uintptr_t, ptr, "p"); |
| } |
| TEST_END |
| |
| TEST_STRUCT(z, size_t) |
| TEST_BEGIN(test_atomic_z) |
| { |
| |
| TEST_BODY(z, size_t, size_t, zu, "#zx"); |
| } |
| TEST_END |
| |
| TEST_STRUCT(u, unsigned) |
| TEST_BEGIN(test_atomic_u) |
| { |
| |
| TEST_BODY(u, unsigned, unsigned, u, "#x"); |
| } |
| TEST_END |
| |
| int |
| main(void) |
| { |
| |
| return (test( |
| test_atomic_uint64, |
| test_atomic_uint32, |
| test_atomic_p, |
| test_atomic_z, |
| test_atomic_u)); |
| } |