]> pd.if.org Git - liblfds/blob - liblfds/liblfds7.0.0/test/src/test_lfds700_queue_enqueuing_and_dequeuing.c
Initial import (all versions, including the new 7.1.0)
[liblfds] / liblfds / liblfds7.0.0 / test / src / test_lfds700_queue_enqueuing_and_dequeuing.c
1 /***** includes *****/
2 #include "internal.h"
3
4 /***** structs *****/
5 struct test_state
6 {
7   enum flag
8     error_flag;
9
10   lfds700_pal_uint_t
11     counter,
12     number_logical_processors,
13     *per_thread_counters,
14     thread_number;
15
16   struct lfds700_queue_state
17     *qs;
18 };
19
20 struct test_element
21 {
22   struct lfds700_queue_element
23     qe,
24     *qe_use;
25
26   lfds700_pal_uint_t
27     counter,
28     thread_number;
29 };
30
31 /***** private prototypes *****/
32 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_enqueuer_and_dequeuer( void *util_thread_starter_thread_state );
33
34
35
36
37
38 /****************************************************************************/
39 void test_lfds700_queue_enqueuing_and_dequeuing( struct lfds700_list_asu_state *list_of_logical_processors )
40 {
41   enum lfds700_misc_validity
42     dvs = LFDS700_MISC_VALIDITY_VALID;
43
44   lfds700_pal_uint_t
45     loop,
46     number_logical_processors,
47     subloop;
48
49   struct lfds700_list_asu_element
50     *lasue;
51
52   struct lfds700_misc_prng_state
53     ps;
54
55   struct lfds700_queue_state
56     qs;
57
58   struct lfds700_misc_validation_info
59     vi;
60
61   struct test_pal_logical_processor
62     *lp;
63
64   struct util_thread_starter_state
65     *tts;
66
67   struct test_element
68     *te_array;
69
70   struct test_state
71     *ts;
72
73   test_pal_thread_state_t
74     *thread_handles;
75
76   assert( list_of_logical_processors != NULL );
77   // TRD : qt can be any value in its range
78
79   /* TRD : create a queue with one element per thread
80            each thread constly dequeues and enqueues from that one queue
81            where when enqueuing sets in the element
82            its thread number and counter
83            and when dequeuing, checks the thread number and counter
84            against previously seen counter for that thread
85            where it should always see a higher number
86   */
87
88   internal_display_test_name( "Enqueuing and dequeuing (%d seconds)", TEST_DURATION_IN_SECONDS );
89
90   lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
91
92   lfds700_misc_prng_init( &ps );
93
94   te_array = util_aligned_malloc( sizeof(struct test_element) * (number_logical_processors+1), LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
95
96   lfds700_queue_init_valid_on_current_logical_core( &qs, &(te_array+number_logical_processors)->qe, &ps, NULL );
97
98   // TRD : we assume the test will iterate at least once (or we'll have a false negative)
99   for( loop = 0 ; loop < number_logical_processors ; loop++ )
100   {
101     (te_array+loop)->thread_number = loop;
102     (te_array+loop)->counter = 0;
103     LFDS700_QUEUE_SET_VALUE_IN_ELEMENT( (te_array+loop)->qe, te_array+loop );
104     lfds700_queue_enqueue( &qs, &(te_array+loop)->qe, &ps );
105   }
106
107   ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
108
109   for( loop = 0 ; loop < number_logical_processors ; loop++ )
110   {
111     (ts+loop)->qs = &qs;
112     (ts+loop)->thread_number = loop;
113     (ts+loop)->counter = 0;
114     (ts+loop)->error_flag = LOWERED;
115     (ts+loop)->per_thread_counters = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_logical_processors );
116     (ts+loop)->number_logical_processors = number_logical_processors;
117
118     for( subloop = 0 ; subloop < number_logical_processors ; subloop++ )
119       *((ts+loop)->per_thread_counters+subloop) = 0;
120   }
121
122   thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
123
124   util_thread_starter_new( &tts, number_logical_processors );
125
126   LFDS700_MISC_BARRIER_STORE;
127
128   lfds700_misc_force_store();
129
130   loop = 0;
131   lasue = NULL;
132
133   while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
134   {
135     lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
136     util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_enqueuer_and_dequeuer, ts+loop );
137     loop++;
138   }
139
140   util_thread_starter_run( tts );
141
142   for( loop = 0 ; loop < number_logical_processors ; loop++ )
143     test_pal_thread_wait( thread_handles[loop] );
144
145   util_thread_starter_delete( tts );
146
147   free( thread_handles );
148
149   LFDS700_MISC_BARRIER_LOAD;
150
151   vi.min_elements = vi.max_elements = number_logical_processors;
152
153   lfds700_queue_query( &qs, LFDS700_QUEUE_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
154
155   for( loop = 0 ; loop < number_logical_processors ; loop++ )
156     if( (ts+loop)->error_flag == RAISED )
157       dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
158
159   for( loop = 0 ; loop < number_logical_processors ; loop++ )
160     free( (ts+loop)->per_thread_counters );
161
162   util_aligned_free( te_array );
163
164   free( ts );
165
166   lfds700_queue_cleanup( &qs, NULL );
167
168   internal_display_test_result( 1, "queue", dvs );
169
170   return;
171 }
172
173
174
175
176
177 /****************************************************************************/
178 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_enqueuer_and_dequeuer( void *util_thread_starter_thread_state )
179 {
180   lfds700_pal_uint_t
181     time_loop = 0;
182
183   struct lfds700_misc_prng_state
184     ps;
185
186   struct lfds700_queue_element
187     *qe;
188
189   struct test_element
190     *te;
191
192   struct test_state
193     *ts;
194
195   struct util_thread_starter_thread_state
196     *tsts;
197
198   time_t
199     current_time,
200     start_time;
201
202   LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
203
204   assert( util_thread_starter_thread_state != NULL );
205
206   tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
207   ts = (struct test_state *) tsts->thread_user_state;
208
209   lfds700_misc_prng_init( &ps );
210
211   util_thread_starter_ready_and_wait( tsts );
212
213   current_time = start_time = time( NULL );
214
215   while( current_time < start_time + TEST_DURATION_IN_SECONDS )
216   {
217     lfds700_queue_dequeue( ts->qs, &qe, &ps );
218     te = LFDS700_QUEUE_GET_VALUE_FROM_ELEMENT( *qe );
219
220     if( te->thread_number >= ts->number_logical_processors )
221       ts->error_flag = RAISED;
222     else
223     {
224       if( te->counter < ts->per_thread_counters[te->thread_number] )
225         ts->error_flag = RAISED;
226
227       if( te->counter >= ts->per_thread_counters[te->thread_number] )
228         ts->per_thread_counters[te->thread_number] = te->counter+1;
229     }
230
231     te->thread_number = ts->thread_number;
232     te->counter = ++ts->counter;
233
234     LFDS700_QUEUE_SET_VALUE_IN_ELEMENT( *qe, te );
235     lfds700_queue_enqueue( ts->qs, qe, &ps );
236
237     if( time_loop++ == TIME_LOOP_COUNT )
238     {
239       time_loop = 0;
240       time( &current_time );
241     }
242   }
243
244   LFDS700_MISC_BARRIER_STORE;
245
246   lfds700_misc_force_store();
247
248   return( (test_pal_thread_return_t) EXIT_SUCCESS );
249 }
250