]> pd.if.org Git - liblfds/blob - liblfds/liblfds7.0.0/test/src/test_lfds700_porting_abstraction_layer_atomic_cas.c
Initial import (all versions, including the new 7.1.0)
[liblfds] / liblfds / liblfds7.0.0 / test / src / test_lfds700_porting_abstraction_layer_atomic_cas.c
1 /***** includes *****/
2 #include "internal.h"
3
4 /***** structs *****/
5 struct test_lfds700_pal_atomic_cas_state
6 {
7   lfds700_pal_uint_t
8     local_counter;
9
10   lfds700_pal_atom_t volatile
11     *shared_counter;
12 };
13
14 /***** private prototyps *****/
15 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_cas( void *util_thread_starter_thread_state );
16
17
18
19
20
21 /****************************************************************************/
22 void test_lfds700_pal_atomic_cas( struct lfds700_list_asu_state *list_of_logical_processors )
23 {
24   lfds700_pal_atom_t volatile LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
25     shared_counter;
26
27   lfds700_pal_uint_t
28     local_total = 0;
29
30   lfds700_pal_uint_t
31     loop,
32     number_logical_processors;
33
34   struct lfds700_list_asu_element
35     *lasue;
36
37   struct test_pal_logical_processor
38     *lp;
39
40   struct util_thread_starter_state
41     *tts;
42
43   struct test_lfds700_pal_atomic_cas_state
44     *atcs;
45
46   test_pal_thread_state_t
47     *thread_handles;
48
49   assert( list_of_logical_processors != NULL );
50
51   /* TRD : here we test pal_cas
52
53            we run one thread per CPU
54            we use pal_cas() to increment a shared counter
55            every time a thread successfully increments the counter,
56            it increments a thread local counter
57            the threads run for ten seconds
58            after the threads finish, we total the local counters
59            they should equal the shared counter
60   */
61
62   internal_display_test_name( "Atomic CAS" );
63
64   lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
65
66   shared_counter = 0;
67
68   atcs = util_malloc_wrapper( sizeof(struct test_lfds700_pal_atomic_cas_state) * number_logical_processors );
69
70   for( loop = 0 ; loop < number_logical_processors ; loop++ )
71   {
72     (atcs+loop)->shared_counter = &shared_counter;
73     (atcs+loop)->local_counter = 0;
74   }
75
76   thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
77
78   util_thread_starter_new( &tts, number_logical_processors );
79
80   LFDS700_MISC_BARRIER_STORE;
81
82   lfds700_misc_force_store();
83
84   loop = 0;
85   lasue = NULL;
86
87   while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
88   {
89     lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
90     util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_cas, atcs+loop );
91     loop++;
92   }
93
94   util_thread_starter_run( tts );
95
96   for( loop = 0 ; loop < number_logical_processors ; loop++ )
97     test_pal_thread_wait( thread_handles[loop] );
98
99   util_thread_starter_delete( tts );
100
101   free( thread_handles );
102
103   // TRD : results
104   LFDS700_MISC_BARRIER_LOAD;
105
106   for( loop = 0 ; loop < number_logical_processors ; loop++ )
107     local_total += (atcs+loop)->local_counter;
108
109   if( local_total == shared_counter )
110     puts( "passed" );
111
112   if( local_total != shared_counter )
113   {
114     puts( "failed" );
115     exit( EXIT_FAILURE );
116   }
117
118   // TRD : cleanup
119   free( atcs );
120
121   return;
122 }
123
124
125
126
127
128 /****************************************************************************/
129 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_cas( void *util_thread_starter_thread_state )
130 {
131   char unsigned 
132     result;
133
134   lfds700_pal_uint_t
135     loop = 0;
136
137   lfds700_pal_atom_t LFDS700_PAL_ALIGN(LFDS700_PAL_ALIGN_SINGLE_POINTER)
138     exchange,
139     compare;
140
141   struct test_lfds700_pal_atomic_cas_state
142     *atcs;
143
144   struct util_thread_starter_thread_state
145     *tsts;
146
147   LFDS700_MISC_BARRIER_LOAD;
148
149   assert( util_thread_starter_thread_state != NULL );
150
151   tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
152   atcs = (struct test_lfds700_pal_atomic_cas_state *) tsts->thread_user_state;
153
154   util_thread_starter_ready_and_wait( tsts );
155
156   while( loop++ < 10000000 )
157   {
158     compare = *atcs->shared_counter;
159
160     do
161     {
162       exchange = compare + 1;
163       LFDS700_PAL_ATOMIC_CAS( atcs->shared_counter, &compare, exchange, LFDS700_MISC_CAS_STRENGTH_WEAK, result );
164     }
165     while( result == 0 );
166
167     atcs->local_counter++;
168   }
169
170   LFDS700_MISC_BARRIER_STORE;
171
172   lfds700_misc_force_store();
173
174   return( (test_pal_thread_return_t) EXIT_SUCCESS );
175 }
176