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