1/* { dg-do link } */ 2/* { dg-require-effective-target sync_long_long_runtime } */ 3/* { dg-options "" } */ 4/* { dg-options "-march=pentium" { target { { i?86-*-* x86_64-*-* } && ia32 } } } */ 5/* { dg-final { simulate-thread } } */ 6 7 8#include <stdio.h> 9#include "simulate-thread.h" 10 11 12/* Testing load for atomicity is a little trickier. 13 14 Set up the atomic value so that it changes value after every instruction 15 is executed. 16 17 Simply alternating between 2 values wouldn't be sufficient since a load of 18 one part, followed by the load of the second part 2 instructions later would 19 appear to be valid. 20 21 set up a table of 16 values which change a bit in every byte of the value 22 each time, this will give us a 16 instruction cycle before repetition 23 kicks in, which should be sufficient to detect any issues. Just to be sure, 24 we also change the table cycle size during execution. 25 26 The end result is that all loads should always get one of the values from 27 the table. Any other pattern means the load failed. */ 28 29unsigned long long ret; 30unsigned long long value = 0; 31unsigned long long result = 0; 32unsigned long long table[16] = { 330x0000000000000000, 340x1111111111111111, 350x2222222222222222, 360x3333333333333333, 370x4444444444444444, 380x5555555555555555, 390x6666666666666666, 400x7777777777777777, 410x8888888888888888, 420x9999999999999999, 430xAAAAAAAAAAAAAAAA, 440xBBBBBBBBBBBBBBBB, 450xCCCCCCCCCCCCCCCC, 460xDDDDDDDDDDDDDDDD, 470xEEEEEEEEEEEEEEEE, 480xFFFFFFFFFFFFFFFF 49}; 50 51int table_cycle_size = 16; 52 53/* Return 0 if 'result' is a valid value to have loaded. */ 54int verify_result () 55{ 56 int x; 57 int found = 0; 58 59 /* Check entire table for valid values. */ 60 for (x = 0; x < 16 ; x++) 61 if (result == table[x]) 62 { 63 found = 1; 64 break; 65 } 66 67 if (!found) 68 printf("FAIL: Invalid result returned from fetch\n"); 69 70 return !found; 71} 72 73/* Iterate VALUE through the different valid values. */ 74void simulate_thread_other_threads () 75{ 76 static int current = 0; 77 78 if (++current >= table_cycle_size) 79 current = 0; 80 value = table[current]; 81} 82 83int simulate_thread_step_verify () 84{ 85 return verify_result (); 86} 87 88int simulate_thread_final_verify () 89{ 90 return verify_result (); 91} 92 93__attribute__((noinline)) 94void simulate_thread_main() 95{ 96 int x; 97 98 /* Execute loads with value changing at various cyclic values. */ 99 for (table_cycle_size = 16; table_cycle_size > 4 ; table_cycle_size--) 100 { 101 ret = __atomic_load_n (&value, __ATOMIC_SEQ_CST); 102 /* In order to verify the returned value (which is not atomic), it needs 103 to be atomically stored into another variable and check that. */ 104 __atomic_store_n (&result, ret, __ATOMIC_SEQ_CST); 105 106 /* Execute the fetch/store a couple of times just to ensure the cycles 107 have a chance to be interesting. */ 108 ret = __atomic_load_n (&value, __ATOMIC_SEQ_CST); 109 __atomic_store_n (&result, ret, __ATOMIC_SEQ_CST); 110 } 111} 112 113int 114main() 115{ 116 simulate_thread_main (); 117 simulate_thread_done (); 118 return 0; 119} 120