1  /* { dg-do link } */
       2  /* { dg-require-effective-target sync_int_128_runtime } */
       3  /* { dg-options "-mcx16" { target { x86_64-*-* i?86-*-* } } } */
       4  /* { dg-final { simulate-thread } } */
       5  
       6  #include <stdio.h>
       7  #include "simulate-thread.h"
       8  
       9  /* Test all the __sync routines for proper atomicity on 16 byte values.  */
      10  
      11  __int128_t zero = 0;
      12  __int128_t max = ~0;
      13  __int128_t changing_value = 0;
      14  __int128_t value = 0;
      15  __int128_t ret;
      16  
      17  void test_abort()
      18  {
      19    static int reported = 0;
      20    if (!reported)
      21      {
      22        printf ("FAIL: improper execution of __sync builtin.\n");
      23        reported = 1;
      24      }
      25  }
      26  
      27  void simulate_thread_other_threads ()
      28  {
      29  }
      30  
      31  int simulate_thread_step_verify ()
      32  {
      33    if (value != zero && value != max)
      34      {
      35        printf ("FAIL: invalid intermediate result for value.\n");
      36        return 1;
      37      }
      38    return 0;
      39  }
      40  
      41  int simulate_thread_final_verify ()
      42  {
      43    if (value != 0)
      44      {
      45        printf ("FAIL: invalid final result for value.\n");
      46        return 1;
      47      }
      48    return 0;
      49  }
      50  
      51  /* All values written to 'value' alternate between 'zero' and 'max'. Any other
      52     value detected by simulate_thread_step_verify() between instructions would indicate
      53     that the value was only partially written, and would thus fail this 
      54     atomicity test.  
      55  
      56     This function tests each different __atomic routine once, with the
      57     exception of the load instruction which requires special testing.  */
      58  __attribute__((noinline))
      59  void simulate_thread_main()
      60  {
      61    
      62    ret = __atomic_exchange_n (&value, max, __ATOMIC_SEQ_CST);
      63    if (ret != zero || value != max)
      64      test_abort();
      65  
      66    __atomic_store_n (&value, zero, __ATOMIC_SEQ_CST);
      67    if (value != zero)
      68      test_abort();
      69  
      70    ret = __atomic_fetch_add (&value, max, __ATOMIC_SEQ_CST);
      71    if (value != max || ret != zero)
      72      test_abort ();
      73  
      74    ret = __atomic_fetch_sub (&value, max, __ATOMIC_SEQ_CST);
      75    if (value != zero || ret != max)
      76      test_abort ();
      77  
      78    ret = __atomic_fetch_or (&value, max, __ATOMIC_SEQ_CST);
      79    if (value != max || ret != zero)
      80      test_abort ();
      81  
      82    ret = __atomic_fetch_and (&value, max, __ATOMIC_SEQ_CST);
      83    if (value != max || ret != max)
      84      test_abort ();
      85  
      86    ret = __atomic_fetch_xor (&value, max, __ATOMIC_SEQ_CST);
      87    if (value != zero || ret != max)
      88      test_abort ();
      89  
      90    ret = __atomic_add_fetch (&value, max, __ATOMIC_SEQ_CST);
      91    if (value != max || ret != max)
      92      test_abort ();
      93  
      94    ret = __atomic_sub_fetch (&value, max, __ATOMIC_SEQ_CST);
      95    if (value != zero || ret != zero)
      96      test_abort ();
      97  
      98    ret = __atomic_or_fetch (&value, max, __ATOMIC_SEQ_CST);
      99    if (value != max || ret != max)
     100      test_abort ();
     101  
     102    ret = __atomic_and_fetch (&value, max, __ATOMIC_SEQ_CST);
     103    if (value != max || ret != max)
     104      test_abort ();
     105  
     106    ret = __atomic_xor_fetch (&value, max, __ATOMIC_SEQ_CST);
     107    if (value != zero || ret != zero)
     108      test_abort ();
     109  }
     110  
     111  int main()
     112  {
     113    simulate_thread_main ();
     114    simulate_thread_done ();
     115    return 0;
     116  }