atomicops.c raw

   1  /*
   2   * Copyright (c) 2017 Ivan Maidanski
   3   *
   4   * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
   5   * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
   6   *
   7   * Permission is hereby granted to use or copy this program
   8   * for any purpose, provided the above notices are retained on all copies.
   9   * Permission to modify the code and to distribute modified code is granted,
  10   * provided the above notices are retained, and a notice that the code was
  11   * modified is included with the above copyright notice.
  12   */
  13  
  14  /*
  15   * Minimal testing of atomic operations used by the collector.
  16   * Primary use is to determine whether the compiler atomic intrinsics
  17   * can be relied on.
  18   */
  19  
  20  #ifdef HAVE_CONFIG_H
  21  #  include "config.h"
  22  #endif
  23  
  24  #include <stdio.h>
  25  
  26  #if defined(GC_BUILTIN_ATOMIC) || defined(GC_THREADS)
  27  
  28  #  include <stdlib.h>
  29  
  30  #  ifdef PARALLEL_MARK
  31  #    define AO_REQUIRE_CAS
  32  #    if !defined(__GNUC__) && !defined(AO_ASSUME_WINDOWS98)
  33  #      define AO_ASSUME_WINDOWS98
  34  #    endif
  35  #  endif
  36  
  37  #  include "private/gc_atomic_ops.h"
  38  
  39  #  define TA_assert(e)                                                   \
  40      if (!(e)) {                                                          \
  41        fprintf(stderr, "Assertion failure, line %d: " #e "\n", __LINE__); \
  42        exit(-1);                                                          \
  43      }
  44  
  45  int
  46  main(void)
  47  {
  48    AO_t x = 13;
  49  #  if defined(AO_HAVE_char_load) || defined(AO_HAVE_char_store)
  50    unsigned char c = 117;
  51  #  endif
  52  #  ifdef AO_HAVE_test_and_set_acquire
  53    AO_TS_t z = AO_TS_INITIALIZER;
  54  
  55    TA_assert(AO_test_and_set_acquire(&z) == AO_TS_CLEAR);
  56    TA_assert(AO_test_and_set_acquire(&z) == AO_TS_SET);
  57    AO_CLEAR(&z);
  58  #  endif
  59    AO_compiler_barrier();
  60  #  ifdef AO_HAVE_nop_full
  61    AO_nop_full();
  62  #  endif
  63  #  ifdef AO_HAVE_char_load
  64    TA_assert(AO_char_load(&c) == 117);
  65  #  endif
  66  #  ifdef AO_HAVE_char_store
  67    AO_char_store(&c, 119);
  68    TA_assert(c == 119);
  69  #  endif
  70  #  ifdef AO_HAVE_load_acquire
  71    TA_assert(AO_load_acquire(&x) == 13);
  72  #  endif
  73  #  if defined(AO_HAVE_fetch_and_add) && defined(AO_HAVE_fetch_and_add1) \
  74        && defined(AO_HAVE_fetch_and_sub1)
  75    TA_assert(AO_fetch_and_add(&x, 42) == 13);
  76    TA_assert(AO_fetch_and_add(&x, (AO_t)(-43)) == 55);
  77    TA_assert(AO_fetch_and_add1(&x) == 12);
  78    TA_assert(AO_fetch_and_sub1(&x) == 13);
  79    TA_assert(AO_fetch_and_add1(&x) == 12); /*< the 2nd call */
  80  #  endif
  81  #  ifdef AO_HAVE_compare_and_swap_release
  82    TA_assert(!AO_compare_and_swap_release(&x, 14, 42));
  83    TA_assert(x == 13);
  84    TA_assert(AO_compare_and_swap_release(&x, 13, 42));
  85    TA_assert(x == 42);
  86  #    ifdef AO_REQUIRE_CAS
  87    {
  88      char *cptr = (char *)NULL;
  89  
  90      TA_assert(GC_cptr_compare_and_swap(&cptr, (char *)NULL, (char *)&x));
  91      TA_assert(cptr == (char *)&x);
  92    }
  93  #    endif
  94  #  else
  95    if (*(volatile AO_t *)&x == 13)
  96      *(volatile AO_t *)&x = 42;
  97  #  endif
  98  #  ifdef AO_HAVE_or
  99    AO_or(&x, 66);
 100    TA_assert(x == 106);
 101  #  endif
 102  #  ifdef AO_HAVE_store_release
 103    AO_store_release(&x, 113);
 104    TA_assert(x == 113);
 105  #  endif
 106    return 0;
 107  }
 108  
 109  #else
 110  
 111  int
 112  main(void)
 113  {
 114    printf("test skipped\n");
 115    return 0;
 116  }
 117  
 118  #endif
 119