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