win-pvdrivers

view liblfds.6/test/src/test_abstraction.c @ 1025:aa2e51f67f7c

Fix hibernate under Win8. Change debugprints.
author James Harper <james.harper@bendigoit.com.au>
date Tue Feb 19 15:14:53 2013 +1100 (2013-02-19)
parents 6300617040e0
children
line source
1 #include "internal.h"
7 /****************************************************************************/
8 void test_abstraction( void )
9 {
10 printf( "\n"
11 "Abstraction Tests\n"
12 "=================\n" );
14 abstraction_test_increment();
15 abstraction_test_dcas();
17 return;
18 }
24 /****************************************************************************/
25 void abstraction_test_increment( void )
26 {
27 unsigned int
28 loop,
29 cpu_count;
31 thread_state_t
32 *thread_handles;
34 atom_t
35 shared_counter = 0,
36 atomic_shared_counter = 0;
38 /* TRD : here we test abstraction_increment
40 first, we run one thread per CPU where each thread increments
41 a shared counter 10,000,000 times - however, this first test
42 does NOT use atomic increment; it uses "++"
44 second, we repeat the exercise, but this time using
45 abstraction_increment()
47 if the final value in the first test is less than (10,000,000*cpu_count)
48 then the system is sensitive to non-atomic increments; this means if
49 our atomic version of the test passes, we can have some degree of confidence
50 that it works
52 if the final value in the first test is in fact correct, then we can't know
53 that our atomic version has changed anything
55 and of course if the final value in the atomic test is wrong, we know things
56 are broken
57 */
59 internal_display_test_name( "Atomic increment" );
61 cpu_count = abstraction_cpu_count();
63 thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
65 // TRD : non-atomic
66 for( loop = 0 ; loop < cpu_count ; loop++ )
67 abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_increment, &shared_counter );
69 for( loop = 0 ; loop < cpu_count ; loop++ )
70 abstraction_thread_wait( thread_handles[loop] );
72 // TRD : atomic
73 for( loop = 0 ; loop < cpu_count ; loop++ )
74 abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_atomic_increment, &atomic_shared_counter );
76 for( loop = 0 ; loop < cpu_count ; loop++ )
77 abstraction_thread_wait( thread_handles[loop] );
79 free( thread_handles );
81 // TRD : results
82 if( shared_counter < (10000000 * cpu_count) and atomic_shared_counter == (10000000 * cpu_count) )
83 puts( "passed" );
85 if( shared_counter == (10000000 * cpu_count) and atomic_shared_counter == (10000000 * cpu_count) )
86 puts( "indeterminate" );
88 if( atomic_shared_counter < (10000000 * cpu_count) )
89 puts( "failed" );
91 return;
92 }
98 /****************************************************************************/
99 thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_increment( void *shared_counter )
100 {
101 volatile atom_t
102 count = 0;
104 /* TRD : atom_t must be volatile or the compiler
105 optimizes it away into a single store
106 */
108 assert( shared_counter != NULL );
110 while( count++ < 10000000 )
111 (*(atom_t *) shared_counter)++;
113 return( (thread_return_t) EXIT_SUCCESS );
114 }
120 /****************************************************************************/
121 thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_atomic_increment( void *shared_counter )
122 {
123 atom_t
124 count = 0;
126 assert( shared_counter != NULL );
128 while( count++ < 10000000 )
129 abstraction_increment( shared_counter );
131 return( (thread_return_t) EXIT_SUCCESS );
132 }
138 /****************************************************************************/
139 void abstraction_test_dcas( void )
140 {
141 unsigned int
142 loop,
143 cpu_count;
145 thread_state_t
146 *thread_handles;
148 struct abstraction_test_dcas_state
149 *atds;
151 ALIGN(ALIGN_DOUBLE_POINTER) volatile atom_t
152 shared_counter[2] = { 0, 0 };
154 atom_t
155 local_total = 0;
157 /* TRD : here we test abstraction_dcas
159 we run one thread per CPU
160 we use abstraction_dcas() to increment a shared counter
161 every time a thread successfully increments the counter,
162 it increments a thread local counter
163 the threads run for ten seconds
164 after the threads finish, we total the local counters
165 they should equal the shared counter
166 */
168 internal_display_test_name( "Atomic DCAS" );
170 cpu_count = abstraction_cpu_count();
172 atds = malloc( sizeof(struct abstraction_test_dcas_state) * cpu_count );
174 for( loop = 0 ; loop < cpu_count ; loop++ )
175 {
176 (atds+loop)->shared_counter = shared_counter;
177 (atds+loop)->local_counter = 0;
178 }
180 thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
182 for( loop = 0 ; loop < cpu_count ; loop++ )
183 abstraction_thread_start( &thread_handles[loop], loop, abstraction_test_internal_thread_dcas, atds+loop );
185 for( loop = 0 ; loop < cpu_count ; loop++ )
186 abstraction_thread_wait( thread_handles[loop] );
188 free( thread_handles );
190 // TRD : results
191 for( loop = 0 ; loop < cpu_count ; loop++ )
192 local_total += (atds+loop)->local_counter;
194 if( local_total == shared_counter[0] )
195 puts( "passed" );
197 if( local_total != shared_counter[0] )
198 puts( "failed" );
200 // TRD : cleanup
201 free( atds );
203 return;
204 }
210 /****************************************************************************/
211 thread_return_t CALLING_CONVENTION abstraction_test_internal_thread_dcas( void *abstraction_test_dcas_state )
212 {
213 struct abstraction_test_dcas_state
214 *atds;
216 time_t
217 start_time;
219 ALIGN(ALIGN_DOUBLE_POINTER) atom_t
220 exchange[2],
221 compare[2];
223 assert( abstraction_test_dcas_state != NULL );
225 atds = (struct abstraction_test_dcas_state *) abstraction_test_dcas_state;
227 time( &start_time );
229 while( time(NULL) < start_time + 10 )
230 {
231 compare[0] = *atds->shared_counter;
232 compare[1] = *(atds->shared_counter+1);
234 do
235 {
236 exchange[0] = compare[0] + 1;
237 exchange[1] = compare[1];
238 }
239 while( 0 == abstraction_dcas(atds->shared_counter, exchange, compare) );
241 atds->local_counter++;
242 }
244 return( (thread_return_t) EXIT_SUCCESS );
245 }