brintos

brintos / llvm-project-archived public Read only

0
0
Text · 24.9 KiB · 346c9b3 Raw
692 lines · c
1// RUN: %clang_builtins %s %librt -o %t && %run %t2// REQUIRES: librt_has_atomic3//===-- atomic_test.c - Test support functions for atomic operations ------===//4//5// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.6// See https://llvm.org/LICENSE.txt for license information.7// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception8//9//===----------------------------------------------------------------------===//10//11// This file performs some simple testing of the support functions for the12// atomic builtins. All tests are single-threaded, so this is only a sanity13// check.14//15//===----------------------------------------------------------------------===//16 17#include <stdbool.h>18#include <stdint.h>19#include <stdio.h>20#include <stdlib.h>21#include <string.h>22#undef NDEBUG23#include <assert.h>24 25// We directly test the library atomic functions, not using the C builtins. This26// should avoid confounding factors, ensuring that we actually test the27// functions themselves, regardless of how the builtins are lowered. We need to28// use asm labels because we can't redeclare the builtins.29// Note: we need to prepend an underscore to this name for e.g. macOS.30#define _STRINGIFY(x) #x31#define STRINGIFY(x) _STRINGIFY(x)32#define EXTERNAL_NAME(name) asm(STRINGIFY(__USER_LABEL_PREFIX__) #name)33 34bool __atomic_is_lock_free_c(size_t size, void *ptr)35    EXTERNAL_NAME(__atomic_is_lock_free);36 37void __atomic_load_c(int size, void *src, void *dest,38                     int model) EXTERNAL_NAME(__atomic_load);39 40uint8_t __atomic_load_1(uint8_t *src, int model);41uint16_t __atomic_load_2(uint16_t *src, int model);42uint32_t __atomic_load_4(uint32_t *src, int model);43uint64_t __atomic_load_8(uint64_t *src, int model);44 45void __atomic_store_c(int size, void *dest, const void *src,46                      int model) EXTERNAL_NAME(__atomic_store);47 48void __atomic_store_1(uint8_t *dest, uint8_t val, int model);49void __atomic_store_2(uint16_t *dest, uint16_t val, int model);50void __atomic_store_4(uint32_t *dest, uint32_t val, int model);51void __atomic_store_8(uint64_t *dest, uint64_t val, int model);52 53void __atomic_exchange_c(int size, void *ptr, const void *val, void *old,54                         int model) EXTERNAL_NAME(__atomic_exchange);55 56uint8_t __atomic_exchange_1(uint8_t *dest, uint8_t val, int model);57uint16_t __atomic_exchange_2(uint16_t *dest, uint16_t val, int model);58uint32_t __atomic_exchange_4(uint32_t *dest, uint32_t val, int model);59uint64_t __atomic_exchange_8(uint64_t *dest, uint64_t val, int model);60 61int __atomic_compare_exchange_c(int size, void *ptr, void *expected,62                                const void *desired, int success, int failure)63    EXTERNAL_NAME(__atomic_compare_exchange);64 65bool __atomic_compare_exchange_1(uint8_t *ptr, uint8_t *expected,66                                 uint8_t desired, int success, int failure);67bool __atomic_compare_exchange_2(uint16_t *ptr, uint16_t *expected,68                                 uint16_t desired, int success, int failure);69bool __atomic_compare_exchange_4(uint32_t *ptr, uint32_t *expected,70                                 uint32_t desired, int success, int failure);71bool __atomic_compare_exchange_8(uint64_t *ptr, uint64_t *expected,72                                 uint64_t desired, int success, int failure);73 74uint8_t __atomic_fetch_add_1(uint8_t *ptr, uint8_t val, int model);75uint16_t __atomic_fetch_add_2(uint16_t *ptr, uint16_t val, int model);76uint32_t __atomic_fetch_add_4(uint32_t *ptr, uint32_t val, int model);77uint64_t __atomic_fetch_add_8(uint64_t *ptr, uint64_t val, int model);78 79uint8_t __atomic_fetch_sub_1(uint8_t *ptr, uint8_t val, int model);80uint16_t __atomic_fetch_sub_2(uint16_t *ptr, uint16_t val, int model);81uint32_t __atomic_fetch_sub_4(uint32_t *ptr, uint32_t val, int model);82uint64_t __atomic_fetch_sub_8(uint64_t *ptr, uint64_t val, int model);83 84uint8_t __atomic_fetch_and_1(uint8_t *ptr, uint8_t val, int model);85uint16_t __atomic_fetch_and_2(uint16_t *ptr, uint16_t val, int model);86uint32_t __atomic_fetch_and_4(uint32_t *ptr, uint32_t val, int model);87uint64_t __atomic_fetch_and_8(uint64_t *ptr, uint64_t val, int model);88 89uint8_t __atomic_fetch_or_1(uint8_t *ptr, uint8_t val, int model);90uint16_t __atomic_fetch_or_2(uint16_t *ptr, uint16_t val, int model);91uint32_t __atomic_fetch_or_4(uint32_t *ptr, uint32_t val, int model);92uint64_t __atomic_fetch_or_8(uint64_t *ptr, uint64_t val, int model);93 94uint8_t __atomic_fetch_xor_1(uint8_t *ptr, uint8_t val, int model);95uint16_t __atomic_fetch_xor_2(uint16_t *ptr, uint16_t val, int model);96uint32_t __atomic_fetch_xor_4(uint32_t *ptr, uint32_t val, int model);97uint64_t __atomic_fetch_xor_8(uint64_t *ptr, uint64_t val, int model);98 99uint8_t __atomic_fetch_nand_1(uint8_t *ptr, uint8_t val, int model);100uint16_t __atomic_fetch_nand_2(uint16_t *ptr, uint16_t val, int model);101uint32_t __atomic_fetch_nand_4(uint32_t *ptr, uint32_t val, int model);102uint64_t __atomic_fetch_nand_8(uint64_t *ptr, uint64_t val, int model);103 104// We conditionally test the *_16 atomic function variants based on the same105// condition that compiler_rt (atomic.c) uses to conditionally generate them.106// Currently atomic.c tests if __SIZEOF_INT128__ is defined (which can be the107// case on 32-bit platforms, by using -fforce-enable-int128), instead of using108// CRT_HAS_128BIT.109 110#ifdef __SIZEOF_INT128__111#define TEST_16112#endif113 114#ifdef TEST_16115typedef __uint128_t uint128_t;116typedef uint128_t maxuint_t;117uint128_t __atomic_load_16(uint128_t *src, int model);118void __atomic_store_16(uint128_t *dest, uint128_t val, int model);119uint128_t __atomic_exchange_16(uint128_t *dest, uint128_t val, int model);120bool __atomic_compare_exchange_16(uint128_t *ptr, uint128_t *expected,121                                  uint128_t desired, int success, int failure);122uint128_t __atomic_fetch_add_16(uint128_t *ptr, uint128_t val, int model);123uint128_t __atomic_fetch_sub_16(uint128_t *ptr, uint128_t val, int model);124uint128_t __atomic_fetch_and_16(uint128_t *ptr, uint128_t val, int model);125uint128_t __atomic_fetch_or_16(uint128_t *ptr, uint128_t val, int model);126uint128_t __atomic_fetch_xor_16(uint128_t *ptr, uint128_t val, int model);127uint128_t __atomic_fetch_nand_16(uint128_t *ptr, uint128_t val, int model);128#else129typedef uint64_t maxuint_t;130#endif131 132#define U8(value) ((uint8_t)(value))133#define U16(value) ((uint16_t)(value))134#define U32(value) ((uint32_t)(value))135#define U64(value) ((uint64_t)(value))136 137#ifdef TEST_16138#define V ((((uint128_t)0x4243444546474849) << 64) | 0x4a4b4c4d4e4f5051)139#define ONES ((((uint128_t)0x0101010101010101) << 64) | 0x0101010101010101)140#else141#define V 0x4243444546474849142#define ONES 0x0101010101010101143#endif144 145#define LEN(array) (sizeof(array) / sizeof(array[0]))146 147__attribute__((aligned(16))) static char data[] = {148    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,149    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,150    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,151    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,152};153 154uint8_t a8, b8;155uint16_t a16, b16;156uint32_t a32, b32;157uint64_t a64, b64;158#ifdef TEST_16159uint128_t a128, b128;160#endif161 162void set_a_values(maxuint_t value) {163  a8 = U8(value);164  a16 = U16(value);165  a32 = U32(value);166  a64 = U64(value);167#ifdef TEST_16168  a128 = value;169#endif170}171 172void set_b_values(maxuint_t value) {173  b8 = U8(value);174  b16 = U16(value);175  b32 = U32(value);176  b64 = U64(value);177#ifdef TEST_16178  b128 = value;179#endif180}181 182void test_loads(void) {183  static int atomic_load_models[] = {184      __ATOMIC_RELAXED,185      __ATOMIC_CONSUME,186      __ATOMIC_ACQUIRE,187      __ATOMIC_SEQ_CST,188  };189 190  for (int m = 0; m < LEN(atomic_load_models); m++) {191    int model = atomic_load_models[m];192 193    // Test with aligned data.194    for (int n = 1; n <= LEN(data); n++) {195      __attribute__((aligned(16))) char dst[LEN(data)] = {0};196      __atomic_load_c(n, data, dst, model);197      if (memcmp(dst, data, n) != 0)198        abort();199    }200 201    // Test with unaligned data.202    for (int n = 1; n < LEN(data); n++) {203      __attribute__((aligned(16))) char dst[LEN(data)] = {0};204      __atomic_load_c(n, data + 1, dst + 1, model);205      if (memcmp(dst + 1, data + 1, n) != 0)206        abort();207    }208 209    set_a_values(V + m);210    if (__atomic_load_1(&a8, model) != U8(V + m))211      abort();212    if (__atomic_load_2(&a16, model) != U16(V + m))213      abort();214    if (__atomic_load_4(&a32, model) != U32(V + m))215      abort();216    if (__atomic_load_8(&a64, model) != U64(V + m))217      abort();218#ifdef TEST_16219    if (__atomic_load_16(&a128, model) != V + m)220      abort();221#endif222  }223}224 225void test_stores(void) {226  static int atomic_store_models[] = {227      __ATOMIC_RELAXED,228      __ATOMIC_RELEASE,229      __ATOMIC_SEQ_CST,230  };231 232  for (int m = 0; m < LEN(atomic_store_models); m++) {233    int model = atomic_store_models[m];234 235    // Test with aligned data.236    for (int n = 1; n <= LEN(data); n++) {237      __attribute__((aligned(16))) char dst[LEN(data)];238      __atomic_store_c(n, dst, data, model);239      if (memcmp(data, dst, n) != 0)240        abort();241    }242 243    // Test with unaligned data.244    for (int n = 1; n < LEN(data); n++) {245      __attribute__((aligned(16))) char dst[LEN(data)];246      __atomic_store_c(n, dst + 1, data + 1, model);247      if (memcmp(data + 1, dst + 1, n) != 0)248        abort();249    }250 251    __atomic_store_1(&a8, U8(V + m), model);252    if (a8 != U8(V + m))253      abort();254    __atomic_store_2(&a16, U16(V + m), model);255    if (a16 != U16(V + m))256      abort();257    __atomic_store_4(&a32, U32(V + m), model);258    if (a32 != U32(V + m))259      abort();260    __atomic_store_8(&a64, U64(V + m), model);261    if (a64 != U64(V + m))262      abort();263#ifdef TEST_16264    __atomic_store_16(&a128, V + m, model);265    if (a128 != V + m)266      abort();267#endif268  }269}270 271void test_exchanges(void) {272  static int atomic_exchange_models[] = {273      __ATOMIC_RELAXED,274      __ATOMIC_ACQUIRE,275      __ATOMIC_RELEASE,276      __ATOMIC_ACQ_REL,277      __ATOMIC_SEQ_CST,278  };279 280  set_a_values(V);281 282  for (int m = 0; m < LEN(atomic_exchange_models); m++) {283    int model = atomic_exchange_models[m];284 285    // Test with aligned data.286    for (int n = 1; n <= LEN(data); n++) {287      __attribute__((aligned(16))) char dst[LEN(data)];288      __attribute__((aligned(16))) char old[LEN(data)];289      for (int i = 0; i < LEN(dst); i++)290        dst[i] = i + m;291      __atomic_exchange_c(n, dst, data, old, model);292      for (int i = 0; i < n; i++) {293        if (dst[i] != 0x10 + i || old[i] != i + m)294          abort();295      }296    }297 298    // Test with unaligned data.299    for (int n = 1; n < LEN(data); n++) {300      __attribute__((aligned(16))) char dst[LEN(data)];301      __attribute__((aligned(16))) char old[LEN(data)];302      for (int i = 1; i < LEN(dst); i++)303        dst[i] = i - 1 + m;304      __atomic_exchange_c(n, dst + 1, data + 1, old + 1, model);305      for (int i = 1; i < n; i++) {306        if (dst[i] != 0x10 + i || old[i] != i - 1 + m)307          abort();308      }309    }310 311    if (__atomic_exchange_1(&a8, U8(V + m + 1), model) != U8(V + m))312      abort();313    if (__atomic_exchange_2(&a16, U16(V + m + 1), model) != U16(V + m))314      abort();315    if (__atomic_exchange_4(&a32, U32(V + m + 1), model) != U32(V + m))316      abort();317    if (__atomic_exchange_8(&a64, U64(V + m + 1), model) != U64(V + m))318      abort();319#ifdef TEST_16320    if (__atomic_exchange_16(&a128, V + m + 1, model) != V + m)321      abort();322#endif323  }324}325 326void test_compare_exchanges(void) {327  static int atomic_compare_exchange_models[] = {328      __ATOMIC_RELAXED,329      __ATOMIC_CONSUME,330      __ATOMIC_ACQUIRE,331      __ATOMIC_SEQ_CST,332      __ATOMIC_RELEASE,333      __ATOMIC_ACQ_REL,334  };335 336  for (int m1 = 0; m1 < LEN(atomic_compare_exchange_models); m1++) {337    // Skip the last two: __ATOMIC_RELEASE and __ATOMIC_ACQ_REL.338    // See <http://wg21.link/p0418> for details.339    for (int m2 = 0; m2 < LEN(atomic_compare_exchange_models) - 2; m2++) {340      int m_succ = atomic_compare_exchange_models[m1];341      int m_fail = atomic_compare_exchange_models[m2];342 343      // Test with aligned data.344      for (int n = 1; n <= LEN(data); n++) {345        __attribute__((aligned(16))) char dst[LEN(data)] = {0};346        __attribute__((aligned(16))) char exp[LEN(data)] = {0};347        if (!__atomic_compare_exchange_c(n, dst, exp, data, m_succ, m_fail))348          abort();349        if (memcmp(dst, data, n) != 0)350          abort();351        if (__atomic_compare_exchange_c(n, dst, exp, data, m_succ, m_fail))352          abort();353        if (memcmp(exp, data, n) != 0)354          abort();355      }356 357      // Test with unaligned data.358      for (int n = 1; n < LEN(data); n++) {359        __attribute__((aligned(16))) char dst[LEN(data)] = {0};360        __attribute__((aligned(16))) char exp[LEN(data)] = {0};361        if (!__atomic_compare_exchange_c(n, dst + 1, exp + 1, data + 1,362                                         m_succ, m_fail))363          abort();364        if (memcmp(dst + 1, data + 1, n) != 0)365          abort();366        if (__atomic_compare_exchange_c(n, dst + 1, exp + 1, data + 1, m_succ,367                                        m_fail))368          abort();369        if (memcmp(exp + 1, data + 1, n) != 0)370          abort();371      }372 373      set_a_values(ONES);374      set_b_values(ONES * 2);375 376      if (__atomic_compare_exchange_1(&a8, &b8, U8(V + m1), m_succ, m_fail))377        abort();378      if (a8 != U8(ONES) || b8 != U8(ONES))379        abort();380      if (!__atomic_compare_exchange_1(&a8, &b8, U8(V + m1), m_succ, m_fail))381        abort();382      if (a8 != U8(V + m1) || b8 != U8(ONES))383        abort();384 385      if (__atomic_compare_exchange_2(&a16, &b16, U16(V + m1), m_succ, m_fail))386        abort();387      if (a16 != U16(ONES) || b16 != U16(ONES))388        abort();389      if (!__atomic_compare_exchange_2(&a16, &b16, U16(V + m1), m_succ, m_fail))390        abort();391      if (a16 != U16(V + m1) || b16 != U16(ONES))392        abort();393 394      if (__atomic_compare_exchange_4(&a32, &b32, U32(V + m1), m_succ, m_fail))395        abort();396      if (a32 != U32(ONES) || b32 != U32(ONES))397        abort();398      if (!__atomic_compare_exchange_4(&a32, &b32, U32(V + m1), m_succ, m_fail))399        abort();400      if (a32 != U32(V + m1) || b32 != U32(ONES))401        abort();402 403      if (__atomic_compare_exchange_8(&a64, &b64, U64(V + m1), m_succ, m_fail))404        abort();405      if (a64 != U64(ONES) || b64 != U64(ONES))406        abort();407      if (!__atomic_compare_exchange_8(&a64, &b64, U64(V + m1), m_succ, m_fail))408        abort();409      if (a64 != U64(V + m1) || b64 != U64(ONES))410        abort();411 412#ifdef TEST_16413      if (__atomic_compare_exchange_16(&a128, &b128, V + m1, m_succ, m_fail))414        abort();415      if (a128 != ONES || b128 != ONES)416        abort();417      if (!__atomic_compare_exchange_16(&a128, &b128, V + m1, m_succ, m_fail))418        abort();419      if (a128 != V + m1 || b128 != ONES)420        abort();421#endif422    }423  }424}425 426void test_fetch_op(void) {427  static int atomic_fetch_models[] = {428      __ATOMIC_RELAXED,429      __ATOMIC_CONSUME,430      __ATOMIC_ACQUIRE,431      __ATOMIC_RELEASE,432      __ATOMIC_ACQ_REL,433      __ATOMIC_SEQ_CST,434  };435 436  for (int m = 0; m < LEN(atomic_fetch_models); m++) {437    int model = atomic_fetch_models[m];438 439    // Fetch add.440 441    set_a_values(V + m);442    set_b_values(0);443    b8 = __atomic_fetch_add_1(&a8, U8(ONES), model);444    if (b8 != U8(V + m) || a8 != U8(V + m + ONES))445      abort();446    b16 = __atomic_fetch_add_2(&a16, U16(ONES), model);447    if (b16 != U16(V + m) || a16 != U16(V + m + ONES))448      abort();449    b32 = __atomic_fetch_add_4(&a32, U32(ONES), model);450    if (b32 != U32(V + m) || a32 != U32(V + m + ONES))451      abort();452    b64 = __atomic_fetch_add_8(&a64, U64(ONES), model);453    if (b64 != U64(V + m) || a64 != U64(V + m + ONES))454      abort();455#ifdef TEST_16456    b128 = __atomic_fetch_add_16(&a128, ONES, model);457    if (b128 != V + m || a128 != V + m + ONES)458      abort();459#endif460 461    // Fetch sub.462 463    set_a_values(V + m);464    set_b_values(0);465    b8 = __atomic_fetch_sub_1(&a8, U8(ONES), model);466    if (b8 != U8(V + m) || a8 != U8(V + m - ONES))467      abort();468    b16 = __atomic_fetch_sub_2(&a16, U16(ONES), model);469    if (b16 != U16(V + m) || a16 != U16(V + m - ONES))470      abort();471    b32 = __atomic_fetch_sub_4(&a32, U32(ONES), model);472    if (b32 != U32(V + m) || a32 != U32(V + m - ONES))473      abort();474    b64 = __atomic_fetch_sub_8(&a64, U64(ONES), model);475    if (b64 != U64(V + m) || a64 != U64(V + m - ONES))476      abort();477#ifdef TEST_16478    b128 = __atomic_fetch_sub_16(&a128, ONES, model);479    if (b128 != V + m || a128 != V + m - ONES)480      abort();481#endif482 483    // Fetch and.484 485    set_a_values(V + m);486    set_b_values(0);487    b8 = __atomic_fetch_and_1(&a8, U8(V + m), model);488    if (b8 != U8(V + m) || a8 != U8(V + m))489      abort();490    b16 = __atomic_fetch_and_2(&a16, U16(V + m), model);491    if (b16 != U16(V + m) || a16 != U16(V + m))492      abort();493    b32 = __atomic_fetch_and_4(&a32, U32(V + m), model);494    if (b32 != U32(V + m) || a32 != U32(V + m))495      abort();496    b64 = __atomic_fetch_and_8(&a64, U64(V + m), model);497    if (b64 != U64(V + m) || a64 != U64(V + m))498      abort();499#ifdef TEST_16500    b128 = __atomic_fetch_and_16(&a128, V + m, model);501    if (b128 != V + m || a128 != V + m)502      abort();503#endif504 505    // Fetch or.506 507    set_a_values(V + m);508    set_b_values(0);509    b8 = __atomic_fetch_or_1(&a8, U8(ONES), model);510    if (b8 != U8(V + m) || a8 != U8((V + m) | ONES))511      abort();512    b16 = __atomic_fetch_or_2(&a16, U16(ONES), model);513    if (b16 != U16(V + m) || a16 != U16((V + m) | ONES))514      abort();515    b32 = __atomic_fetch_or_4(&a32, U32(ONES), model);516    if (b32 != U32(V + m) || a32 != U32((V + m) | ONES))517      abort();518    b64 = __atomic_fetch_or_8(&a64, U64(ONES), model);519    if (b64 != U64(V + m) || a64 != U64((V + m) | ONES))520      abort();521#ifdef TEST_16522    b128 = __atomic_fetch_or_16(&a128, ONES, model);523    if (b128 != V + m || a128 != ((V + m) | ONES))524      abort();525#endif526 527    // Fetch xor.528 529    set_a_values(V + m);530    set_b_values(0);531    b8 = __atomic_fetch_xor_1(&a8, U8(ONES), model);532    if (b8 != U8(V + m) || a8 != U8((V + m) ^ ONES))533      abort();534    b16 = __atomic_fetch_xor_2(&a16, U16(ONES), model);535    if (b16 != U16(V + m) || a16 != U16((V + m) ^ ONES))536      abort();537    b32 = __atomic_fetch_xor_4(&a32, U32(ONES), model);538    if (b32 != U32(V + m) || a32 != U32((V + m) ^ ONES))539      abort();540    b64 = __atomic_fetch_xor_8(&a64, U64(ONES), model);541    if (b64 != U64(V + m) || a64 != U64((V + m) ^ ONES))542      abort();543#ifdef TEST_16544    b128 = __atomic_fetch_xor_16(&a128, ONES, model);545    if (b128 != (V + m) || a128 != ((V + m) ^ ONES))546      abort();547#endif548 549    // Fetch nand.550 551    set_a_values(V + m);552    set_b_values(0);553    b8 = __atomic_fetch_nand_1(&a8, U8(ONES), model);554    if (b8 != U8(V + m) || a8 != U8(~((V + m) & ONES)))555      abort();556    b16 = __atomic_fetch_nand_2(&a16, U16(ONES), model);557    if (b16 != U16(V + m) || a16 != U16(~((V + m) & ONES)))558      abort();559    b32 = __atomic_fetch_nand_4(&a32, U32(ONES), model);560    if (b32 != U32(V + m) || a32 != U32(~((V + m) & ONES)))561      abort();562    b64 = __atomic_fetch_nand_8(&a64, U64(ONES), model);563    if (b64 != U64(V + m) || a64 != U64(~((V + m) & ONES)))564      abort();565#ifdef TEST_16566    b128 = __atomic_fetch_nand_16(&a128, ONES, model);567    if (b128 != (V + m) || a128 != ~((V + m) & ONES))568      abort();569#endif570 571    // Check signed integer overflow behavior572 573    set_a_values(V + m);574    __atomic_fetch_add_1(&a8, U8(V), model);575    if (a8 != U8(V * 2 + m))576      abort();577    __atomic_fetch_sub_1(&a8, U8(V), model);578    if (a8 != U8(V + m))579      abort();580    __atomic_fetch_add_2(&a16, U16(V), model);581    if (a16 != U16(V * 2 + m))582      abort();583    __atomic_fetch_sub_2(&a16, U16(V), model);584    if (a16 != U16(V + m))585      abort();586    __atomic_fetch_add_4(&a32, U32(V), model);587    if (a32 != U32(V * 2 + m))588      abort();589    __atomic_fetch_sub_4(&a32, U32(V), model);590    if (a32 != U32(V + m))591      abort();592    __atomic_fetch_add_8(&a64, U64(V), model);593    if (a64 != U64(V * 2 + m))594      abort();595    __atomic_fetch_sub_8(&a64, U64(V), model);596    if (a64 != U64(V + m))597      abort();598#ifdef TEST_16599    __atomic_fetch_add_16(&a128, V, model);600    if (a128 != V * 2 + m)601      abort();602    __atomic_fetch_sub_16(&a128, V, model);603    if (a128 != V + m)604      abort();605#endif606  }607}608 609void test_is_lock_free(void) {610  // The result of __atomic_is_lock_free is architecture dependent, so we only611  // check for a true return value for the sizes where we know that at compile612  // time that they are supported. If __atomic_always_lock_free() returns false613  // for a given size, we can only check that __atomic_is_lock_free() returns614  // false for unaligned values.615  // Note: This assumption will have to be revisited when we support an616  // architecture that allows for unaligned atomics.617  // XXX: Do any architectures report true for unaligned atomics?618 619  // All atomic.c implementations fall back to the non-specialized case for620  // size=0, so despite the operation being a no-op, they still take locks and621  // therefore __atomic_is_lock_free should return false.622  assert(!__atomic_is_lock_free_c(0, NULL) && "size zero should never be lock-free");623  assert(!__atomic_is_lock_free_c(0, (void *)8) && "size zero should never be lock-free");624 625  if (__atomic_always_lock_free(1, 0)) {626    assert(__atomic_is_lock_free_c(1, NULL) && "aligned size=1 should always be lock-free");627    assert(__atomic_is_lock_free_c(1, (void *)1) && "aligned size=1 should always be lock-free");628  }629 630  if (__atomic_always_lock_free(2, 0)) {631    assert(__atomic_is_lock_free_c(2, NULL) && "aligned size=2 should always be lock-free");632    assert(__atomic_is_lock_free_c(2, (void *)2) && "aligned size=2 should always be lock-free");633  }634  assert(!__atomic_is_lock_free_c(2, (void *)1) && "unaligned size=2 should not be lock-free");635 636  if (__atomic_always_lock_free(4, 0)) {637    assert(__atomic_is_lock_free_c(4, NULL) && "aligned size=4 should always be lock-free");638    assert(__atomic_is_lock_free_c(4, (void *)4) && "aligned size=4 should always be lock-free");639  }640  assert(!__atomic_is_lock_free_c(4, (void *)3) && "unaligned size=4 should not be lock-free");641  assert(!__atomic_is_lock_free_c(4, (void *)2) && "unaligned size=4 should not be lock-free");642  assert(!__atomic_is_lock_free_c(4, (void *)1) && "unaligned size=4 should not be lock-free");643 644  if (__atomic_always_lock_free(8, 0)) {645    assert(__atomic_is_lock_free_c(8, NULL) && "aligned size=8 should always be lock-free");646    assert(__atomic_is_lock_free_c(8, (void *)8) && "aligned size=8 should always be lock-free");647  }648  assert(!__atomic_is_lock_free_c(8, (void *)7) && "unaligned size=8 should not be lock-free");649  assert(!__atomic_is_lock_free_c(8, (void *)4) && "unaligned size=8 should not be lock-free");650  assert(!__atomic_is_lock_free_c(8, (void *)2) && "unaligned size=8 should not be lock-free");651  assert(!__atomic_is_lock_free_c(8, (void *)1) && "unaligned size=8 should not be lock-free");652 653  if (__atomic_always_lock_free(16, 0)) {654    assert(__atomic_is_lock_free_c(16, NULL) && "aligned size=16 should always be lock-free");655    assert(__atomic_is_lock_free_c(16, (void *)16) && "aligned size=16 should always be lock-free");656  }657  assert(!__atomic_is_lock_free_c(16, (void *)15) && "unaligned size=16 should not be lock-free");658  assert(!__atomic_is_lock_free_c(16, (void *)8) && "unaligned size=16 should not be lock-free");659  assert(!__atomic_is_lock_free_c(16, (void *)4) && "unaligned size=16 should not be lock-free");660  assert(!__atomic_is_lock_free_c(16, (void *)2) && "unaligned size=16 should not be lock-free");661  assert(!__atomic_is_lock_free_c(16, (void *)1) && "unaligned size=16 should not be lock-free");662 663  // In the current implementation > 16 bytes are never lock-free:664  assert(!__atomic_is_lock_free_c(32, NULL) && "aligned size=32 should not be lock-free");665  assert(!__atomic_is_lock_free_c(32, (void*)32) && "aligned size=32 should not be lock-free");666  assert(!__atomic_is_lock_free_c(32, (void*)31) && "unaligned size=32 should not be lock-free");667 668  // We also don't support non-power-of-two sizes:669  assert(!__atomic_is_lock_free_c(3, NULL) && "aligned size=3 should not be lock-free");670  assert(!__atomic_is_lock_free_c(5, NULL) && "aligned size=5 should not be lock-free");671  assert(!__atomic_is_lock_free_c(6, NULL) && "aligned size=6 should not be lock-free");672  assert(!__atomic_is_lock_free_c(7, NULL) && "aligned size=7 should not be lock-free");673  assert(!__atomic_is_lock_free_c(9, NULL) && "aligned size=9 should not be lock-free");674  assert(!__atomic_is_lock_free_c(10, NULL) && "aligned size=10 should not be lock-free");675  assert(!__atomic_is_lock_free_c(11, NULL) && "aligned size=11 should not be lock-free");676  assert(!__atomic_is_lock_free_c(12, NULL) && "aligned size=12 should not be lock-free");677  assert(!__atomic_is_lock_free_c(13, NULL) && "aligned size=13 should not be lock-free");678  assert(!__atomic_is_lock_free_c(14, NULL) && "aligned size=14 should not be lock-free");679  assert(!__atomic_is_lock_free_c(15, NULL) && "aligned size=15 should not be lock-free");680  assert(!__atomic_is_lock_free_c(17, NULL) && "aligned size=17 should not be lock-free");681}682 683int main() {684  test_loads();685  test_stores();686  test_exchanges();687  test_compare_exchanges();688  test_fetch_op();689  test_is_lock_free();690  return 0;691}692