]> pd.if.org Git - liblfds/blob - liblfds/liblfds7.0.0/test/src/test_lfds700_stack_popping_and_pushing.c
Initial import (all versions, including the new 7.1.0)
[liblfds] / liblfds / liblfds7.0.0 / test / src / test_lfds700_stack_popping_and_pushing.c
1 /***** includes *****/
2 #include "internal.h"
3
4 /***** structs *****/
5 struct test_element;
6
7 struct test_state
8 {
9   lfds700_pal_uint_t
10     number_elements;
11
12   struct lfds700_stack_state
13     *ss,
14     ss_thread_local;
15
16   struct test_element
17     *ss_thread_local_te_array;
18 };
19
20 struct test_element
21 {
22   struct lfds700_stack_element
23     se,
24     thread_local_se;
25
26   lfds700_pal_uint_t
27     datum;
28 };
29
30 /***** private prototypes *****/
31 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping_and_pushing_start_popping( void *util_thread_starter_thread_state );
32 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping_and_pushing_start_pushing( void *util_thread_starter_thread_state );
33
34
35
36
37
38 /****************************************************************************/
39 void test_lfds700_stack_popping_and_pushing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
40 {
41   enum lfds700_misc_validity
42     dvs = LFDS700_MISC_VALIDITY_VALID;
43
44   lfds700_pal_uint_t
45     loop,
46     number_elements,
47     number_logical_processors,
48     subloop;
49
50   struct lfds700_list_asu_element
51     *lasue;
52
53   struct lfds700_misc_prng_state
54     ps;
55
56   struct lfds700_stack_state
57     ss;
58
59   struct lfds700_misc_validation_info
60     vi;
61
62   struct test_pal_logical_processor
63     *lp;
64
65   struct util_thread_starter_state
66     *tts;
67
68   struct test_element
69     *te_array;
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 have two threads per CPU
81            the threads loop for ten seconds
82            the first thread pushes 10000 elements then pops 10000 elements
83            the second thread pops 10000 elements then pushes 10000 elements
84            all pushes and pops go onto the single main stack
85
86            after time is up, all threads push what they have remaining onto
87            the main stack
88
89            we then validate the main stack
90   */
91
92   internal_display_test_name( "Popping and pushing (%d seconds)", TEST_DURATION_IN_SECONDS );
93
94   lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
95
96   lfds700_misc_prng_init( &ps );
97
98   number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors * 2 );
99
100   lfds700_stack_init_valid_on_current_logical_core( &ss, NULL );
101
102   te_array = util_aligned_malloc( sizeof(struct test_element) * number_elements * number_logical_processors, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
103
104   // TRD : some initial elements so the pushing threads can start immediately
105   for( loop = 0 ; loop < number_elements * number_logical_processors ; loop++ )
106   {
107     (te_array+loop)->datum = loop;
108     LFDS700_STACK_SET_VALUE_IN_ELEMENT( (te_array+loop)->se, te_array+loop );
109     lfds700_stack_push( &ss, &(te_array+loop)->se, &ps );
110   }
111
112   ts = util_aligned_malloc( sizeof(struct test_state) * number_logical_processors * 2, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
113
114   for( loop = 0 ; loop < number_logical_processors ; loop++ )
115   {
116     // TRD : first set of threads
117     (ts+loop)->ss = &ss;
118     (ts+loop)->number_elements = number_elements;
119     lfds700_stack_init_valid_on_current_logical_core( &(ts+loop)->ss_thread_local, NULL );
120
121     // TRD : second set of threads
122     (ts+loop+number_logical_processors)->ss = &ss;
123     (ts+loop+number_logical_processors)->number_elements = number_elements;
124     lfds700_stack_init_valid_on_current_logical_core( &(ts+loop+number_logical_processors)->ss_thread_local, NULL );
125
126     // TRD : fill the pushing thread stacks
127     (ts+loop+number_logical_processors)->ss_thread_local_te_array = util_aligned_malloc( sizeof(struct test_element) * number_elements, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
128
129     for( subloop = 0 ; subloop < number_elements ; subloop++ )
130     {
131       ((ts+loop+number_logical_processors)->ss_thread_local_te_array+subloop)->datum = loop;
132       LFDS700_STACK_SET_VALUE_IN_ELEMENT( ((ts+loop+number_logical_processors)->ss_thread_local_te_array+subloop)->thread_local_se, (ts+loop+number_logical_processors)->ss_thread_local_te_array+subloop );
133       lfds700_stack_push( &(ts+loop+number_logical_processors)->ss_thread_local, &((ts+loop+number_logical_processors)->ss_thread_local_te_array+subloop)->thread_local_se, &ps );
134     }
135   }
136
137   thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors * 2 );
138
139   util_thread_starter_new( &tts, number_logical_processors * 2 );
140
141   LFDS700_MISC_BARRIER_STORE;
142
143   lfds700_misc_force_store();
144
145   loop = 0;
146   lasue = NULL;
147
148   while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
149   {
150     lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
151     util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_popping_and_pushing_start_popping, ts+loop );
152     util_thread_starter_start( tts, &thread_handles[loop+number_logical_processors], loop+number_logical_processors, lp, thread_popping_and_pushing_start_pushing, ts+loop+number_logical_processors );
153     loop++;
154   }
155
156   util_thread_starter_run( tts );
157
158   for( loop = 0 ; loop < number_logical_processors * 2 ; loop++ )
159     test_pal_thread_wait( thread_handles[loop] );
160
161   util_thread_starter_delete( tts );
162
163   free( thread_handles );
164
165   LFDS700_MISC_BARRIER_LOAD;
166
167   vi.min_elements = vi.max_elements = number_elements * number_logical_processors * 2;
168
169   lfds700_stack_query( &ss, LFDS700_STACK_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
170
171   lfds700_stack_cleanup( &ss, NULL );
172
173   for( loop = 0 ; loop < number_logical_processors ; loop++ )
174   {
175     lfds700_stack_cleanup( &(ts+loop)->ss_thread_local, NULL );
176     lfds700_stack_cleanup( &(ts+loop+number_logical_processors)->ss_thread_local, NULL );
177     util_aligned_free( (ts+loop+number_logical_processors)->ss_thread_local_te_array );
178   }
179
180   util_aligned_free( ts );
181
182   util_aligned_free( te_array );
183
184   // TRD : print the test result
185   internal_display_test_result( 1, "stack", dvs );
186
187   return;
188 }
189
190
191
192
193
194
195 /****************************************************************************/
196 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping_and_pushing_start_popping( void *util_thread_starter_thread_state )
197 {
198   lfds700_pal_uint_t
199     count;
200
201   struct lfds700_misc_prng_state
202     ps;
203
204   struct lfds700_stack_element
205     *se;
206
207   struct test_state
208     *ts;
209
210   struct util_thread_starter_thread_state
211     *tsts;
212
213   time_t
214     start_time;
215
216   LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
217
218   assert( util_thread_starter_thread_state != NULL );
219
220   tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
221   ts = (struct test_state *) tsts->thread_user_state;
222
223   lfds700_misc_prng_init( &ps );
224
225   util_thread_starter_ready_and_wait( tsts );
226
227   start_time = time( NULL );
228
229   while( time(NULL) < start_time + TEST_DURATION_IN_SECONDS )
230   {
231     count = 0;
232
233     while( count < ts->number_elements )
234       if( lfds700_stack_pop(ts->ss, &se, &ps) )
235       {
236         lfds700_stack_push( &ts->ss_thread_local, se, &ps );
237         count++;
238       }
239
240     // TRD : return our local stack to the main stack
241     while( lfds700_stack_pop(&ts->ss_thread_local, &se, &ps) )
242       lfds700_stack_push( ts->ss, se, &ps );
243   }
244
245   LFDS700_MISC_BARRIER_STORE;
246
247   lfds700_misc_force_store();
248
249   return( (test_pal_thread_return_t) EXIT_SUCCESS );
250 }
251
252
253
254
255
256 /****************************************************************************/
257 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping_and_pushing_start_pushing( void *util_thread_starter_thread_state )
258 {
259   lfds700_pal_uint_t
260     count;
261
262   struct lfds700_misc_prng_state
263     ps;
264
265   struct lfds700_stack_element
266     *se;
267
268   struct test_state
269     *ts;
270
271   struct util_thread_starter_thread_state
272     *tsts;
273
274   time_t
275     start_time;
276
277   LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
278
279   assert( util_thread_starter_thread_state != NULL );
280
281   tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
282   ts = (struct test_state *) tsts->thread_user_state;
283
284   lfds700_misc_prng_init( &ps );
285
286   util_thread_starter_ready_and_wait( tsts );
287
288   start_time = time( NULL );
289
290   while( time(NULL) < start_time + TEST_DURATION_IN_SECONDS )
291   {
292     // TRD : return our local stack to the main stack
293     while( lfds700_stack_pop(&ts->ss_thread_local, &se, &ps) )
294       lfds700_stack_push( ts->ss, se, &ps );
295
296     count = 0;
297
298     while( count < ts->number_elements )
299       if( lfds700_stack_pop(ts->ss, &se, &ps) )
300       {
301         lfds700_stack_push( &ts->ss_thread_local, se, &ps );
302         count++;
303       }
304   }
305
306   // TRD : now push whatever we have in our local stack
307   while( lfds700_stack_pop(&ts->ss_thread_local, &se, &ps) )
308     lfds700_stack_push( ts->ss, se, &ps );
309
310   LFDS700_MISC_BARRIER_STORE;
311
312   lfds700_misc_force_store();
313
314   return( (test_pal_thread_return_t) EXIT_SUCCESS );
315 }
316