OSDN Git Service

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