]> pd.if.org Git - liblfds/blob - liblfds/liblfds7.0.0/test/src/test_lfds700_freelist_popping_and_pushing.c
Initial import (all versions, including the new 7.1.0)
[liblfds] / liblfds / liblfds7.0.0 / test / src / test_lfds700_freelist_popping_and_pushing.c
1 /***** includes *****/
2 #include "internal.h"
3
4 /***** structs *****/
5 struct test_element;
6
7 struct test_state
8 {
9   struct lfds700_freelist_state
10     fs_thread_local,
11     *fs;
12
13   lfds700_pal_uint_t
14     number_elements;
15
16   struct test_element
17     *fs_thread_local_te_array;
18 };
19
20 struct test_element
21 {
22   struct lfds700_freelist_element
23     fe,
24     thread_local_fe;
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_freelist_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;
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_freelist_state
54     fs;
55
56   struct lfds700_misc_prng_state
57     ps;
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 freelist
85            with a per-thread local freelist to store the pops
86
87            after time is up, all threads push what they have remaining onto
88            the main freelist
89
90            we then validate the main freelist
91   */
92
93   internal_display_test_name( "Popping and pushing (%d seconds)", TEST_DURATION_IN_SECONDS );
94
95   lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
96
97   lfds700_misc_prng_init( &ps );
98
99   number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors * 2 );
100
101   lfds700_freelist_init_valid_on_current_logical_core( &fs, NULL );
102
103   // TRD : we allocate half the total elements here, and half again later, which is why *2 above, but not here
104   te_array = util_aligned_malloc( sizeof(struct test_element) * number_elements * number_logical_processors, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
105
106   // TRD : initial elements in the main freelist so the popping threads can start immediately
107   for( loop = 0 ; loop < number_elements * number_logical_processors ; loop++ )
108   {
109     (te_array+loop)->datum = loop;
110     LFDS700_FREELIST_SET_VALUE_IN_ELEMENT( (te_array+loop)->fe, te_array+loop );
111     lfds700_freelist_push( &fs, &(te_array+loop)->fe, &ps );
112   }
113
114   ts = util_aligned_malloc( sizeof(struct test_state) * number_logical_processors * 2, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
115
116   for( loop = 0 ; loop < number_logical_processors ; loop++ )
117   {
118     // TRD : first set of threads (poppers)
119     (ts+loop)->fs = &fs;
120     (ts+loop)->number_elements = number_elements;
121     lfds700_freelist_init_valid_on_current_logical_core( &(ts+loop)->fs_thread_local, NULL );
122
123     // TRD : second set of threads (pushers - who need elements in their per-thread freelists)
124     (ts+loop+number_logical_processors)->fs = &fs;
125     (ts+loop+number_logical_processors)->number_elements = number_elements;
126     lfds700_freelist_init_valid_on_current_logical_core( &(ts+loop+number_logical_processors)->fs_thread_local, NULL );
127
128     // TRD : fill the pushing thread freelists
129     (ts+loop+number_logical_processors)->fs_thread_local_te_array = util_aligned_malloc( sizeof(struct test_element) * number_elements, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
130
131     for( subloop = 0 ; subloop < number_elements ; subloop++ )
132     {
133       ((ts+loop+number_logical_processors)->fs_thread_local_te_array+subloop)->datum = loop;
134       LFDS700_FREELIST_SET_VALUE_IN_ELEMENT( ((ts+loop+number_logical_processors)->fs_thread_local_te_array+subloop)->thread_local_fe, (ts+loop+number_logical_processors)->fs_thread_local_te_array+subloop );
135       lfds700_freelist_push( &(ts+loop+number_logical_processors)->fs_thread_local, &((ts+loop+number_logical_processors)->fs_thread_local_te_array+subloop)->thread_local_fe, &ps );
136     }
137   }
138
139   thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors * 2 );
140
141   util_thread_starter_new( &tts, number_logical_processors * 2 );
142
143   LFDS700_MISC_BARRIER_STORE;
144
145   lfds700_misc_force_store();
146
147   loop = 0;
148   lasue = NULL;
149
150   while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
151   {
152     lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
153     util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_popping_and_pushing_start_popping, ts+loop );
154     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 );
155     loop++;
156   }
157
158   util_thread_starter_run( tts );
159
160   for( loop = 0 ; loop < number_logical_processors * 2 ; loop++ )
161     test_pal_thread_wait( thread_handles[loop] );
162
163   util_thread_starter_delete( tts );
164
165   free( thread_handles );
166
167   LFDS700_MISC_BARRIER_LOAD;
168
169   vi.min_elements = vi.max_elements = number_elements * number_logical_processors * 2;
170
171   lfds700_freelist_query( &fs, LFDS700_FREELIST_QUERY_SINGLETHREADED_VALIDATE, (void *) &vi, (void *) &dvs );
172
173   lfds700_freelist_cleanup( &fs, NULL );
174
175   for( loop = 0 ; loop < number_logical_processors ; loop++ )
176   {
177     lfds700_freelist_cleanup( &(ts+loop)->fs_thread_local, NULL );
178     lfds700_freelist_cleanup( &(ts+loop+number_logical_processors)->fs_thread_local, NULL );
179     util_aligned_free( (ts+loop+number_logical_processors)->fs_thread_local_te_array );
180   }
181
182   util_aligned_free( ts );
183
184   util_aligned_free( te_array );
185
186   // TRD : print the test result
187   internal_display_test_result( 1, "freelist", dvs );
188
189   return;
190 }
191
192
193
194
195
196
197 /****************************************************************************/
198 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping_and_pushing_start_popping( void *util_thread_starter_thread_state )
199 {
200   lfds700_pal_uint_t
201     count;
202
203   struct lfds700_freelist_element
204     *fe;
205
206   struct lfds700_misc_prng_state
207     ps;
208
209   struct util_thread_starter_thread_state
210     *tsts;
211
212   struct test_state
213     *ts;
214
215   time_t
216     start_time;
217
218   LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
219
220   assert( util_thread_starter_thread_state != NULL );
221
222   tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
223   ts = (struct test_state *) tsts->thread_user_state;
224
225   lfds700_misc_prng_init( &ps );
226
227   util_thread_starter_ready_and_wait( tsts );
228
229   start_time = time( NULL );
230
231   while( time(NULL) < start_time + TEST_DURATION_IN_SECONDS )
232   {
233     count = 0;
234
235     while( count < ts->number_elements )
236       if( lfds700_freelist_pop(ts->fs, &fe, &ps) )
237       {
238         // TRD : we do nothing with the test data, so there'ss no GET or SET here
239         lfds700_freelist_push( &ts->fs_thread_local, fe, &ps );
240         count++;
241       }
242
243     // TRD : return our local freelist to the main freelist
244     while( lfds700_freelist_pop(&ts->fs_thread_local, &fe, &ps) )
245       lfds700_freelist_push( ts->fs, fe, &ps );
246   }
247
248   LFDS700_MISC_BARRIER_STORE;
249
250   lfds700_misc_force_store();
251
252   return( (test_pal_thread_return_t) EXIT_SUCCESS );
253 }
254
255
256
257
258
259 /****************************************************************************/
260 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping_and_pushing_start_pushing( void *util_thread_starter_thread_state )
261 {
262   lfds700_pal_uint_t
263     count;
264
265   struct lfds700_freelist_element
266     *fe;
267
268   struct lfds700_misc_prng_state
269     ps;
270
271   struct test_state
272     *ts;
273
274   struct util_thread_starter_thread_state
275     *tsts;
276
277   time_t
278     start_time;
279
280   LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
281
282   assert( util_thread_starter_thread_state != NULL );
283
284   tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
285   ts = (struct test_state *) tsts->thread_user_state;
286
287   lfds700_misc_prng_init( &ps );
288
289   util_thread_starter_ready_and_wait( tsts );
290
291   start_time = time( NULL );
292
293   while( time(NULL) < start_time + TEST_DURATION_IN_SECONDS )
294   {
295     // TRD : return our local freelist to the main freelist
296     while( lfds700_freelist_pop(&ts->fs_thread_local, &fe, &ps) )
297       lfds700_freelist_push( ts->fs, fe, &ps );
298
299     count = 0;
300
301     while( count < ts->number_elements )
302       if( lfds700_freelist_pop(ts->fs, &fe, &ps) )
303       {
304         lfds700_freelist_push( &ts->fs_thread_local, fe, &ps );
305         count++;
306       }
307   }
308
309   // TRD : now push whatever we have in our local freelist
310   while( lfds700_freelist_pop(&ts->fs_thread_local, &fe, &ps) )
311     lfds700_freelist_push( ts->fs, fe, &ps );
312
313   LFDS700_MISC_BARRIER_STORE;
314
315   lfds700_misc_force_store();
316
317   return( (test_pal_thread_return_t) EXIT_SUCCESS );
318 }
319