]> pd.if.org Git - liblfds/blob - liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_freelist_without_ea_popping_and_pushing.c
Initial import (all versions, including the new 7.1.0)
[liblfds] / liblfds / liblfds7.1.0 / test_and_benchmark / libtest / src / libtest_tests / libtest_tests_freelist_without_ea_popping_and_pushing.c
1 /***** includes *****/
2 #include "libtest_tests_internal.h"
3
4 /***** structs *****/
5 struct test_element;
6
7 struct test_per_thread_state
8 {
9   struct lfds710_freelist_state
10     fs_thread_local,
11     *fs;
12
13   lfds710_pal_uint_t
14     number_elements_per_thread;
15 };
16
17 struct test_element
18 {
19   struct lfds710_freelist_element
20     fe,
21     thread_local_fe;
22
23   lfds710_pal_uint_t
24     datum;
25 };
26
27 /***** private prototypes *****/
28 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_popping_and_pushing_start_popping( void *libtest_threadset_per_thread_state );
29 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_popping_and_pushing_start_pushing( void *libtest_threadset_per_thread_state );
30
31
32
33
34
35 /****************************************************************************/
36 void libtest_tests_freelist_without_ea_popping_and_pushing( struct lfds710_list_asu_state *list_of_logical_processors, struct libshared_memory_state *ms, enum lfds710_misc_validity *dvs )
37 {
38   lfds710_pal_uint_t
39     loop,
40     number_elements,
41     number_elements_per_thread,
42     number_logical_processors,
43     subloop;
44
45   struct lfds710_list_asu_element
46     *lasue = NULL;
47
48   struct lfds710_freelist_state
49     fs;
50
51   struct lfds710_misc_validation_info
52     vi;
53
54   struct libtest_logical_processor
55     *lp;
56
57   struct libtest_threadset_per_thread_state
58     *pts;
59
60   struct libtest_threadset_state
61     ts;
62
63   struct test_element
64     *te_array;
65
66   struct test_per_thread_state
67     *tpts;
68
69   LFDS710_PAL_ASSERT( list_of_logical_processors != NULL );
70   LFDS710_PAL_ASSERT( ms != NULL );
71   LFDS710_PAL_ASSERT( dvs != NULL );
72
73   /* TRD : we have two threads per CPU
74            the threads loop for ten feconds
75            the first thread pushes 10000 elements then pops 10000 elements
76            the fecond thread pops 10000 elements then pushes 10000 elements
77            all pushes and pops go onto the single main freelist
78            with a per-thread local freelist to store the pops
79
80            after time is up, all threads push what they have remaining onto
81            the main freelist
82
83            we then validate the main freelist
84   */
85
86   *dvs = LFDS710_MISC_VALIDITY_VALID;
87
88   lfds710_list_asu_query( list_of_logical_processors, LFDS710_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
89
90   // TRD : allocate
91   tpts = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct test_per_thread_state) * number_logical_processors * 2, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
92   pts = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct libtest_threadset_per_thread_state) * number_logical_processors * 2, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
93   te_array = libshared_memory_alloc_largest_possible_array_from_unknown_node( ms, sizeof(struct test_element), LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES, &number_elements );
94
95   number_elements_per_thread = number_elements / (number_logical_processors * 2);
96
97   lfds710_freelist_init_valid_on_current_logical_core( &fs, NULL, 0, NULL );
98
99   // TRD : half of all elements in the main freelist so the popping threads can start immediately
100   for( loop = 0 ; loop < number_elements_per_thread * number_logical_processors ; loop++ )
101   {
102     (te_array+loop)->datum = loop;
103     LFDS710_FREELIST_SET_VALUE_IN_ELEMENT( (te_array+loop)->fe, te_array+loop );
104     lfds710_freelist_push( &fs, &(te_array+loop)->fe, NULL );
105   }
106
107   libtest_threadset_init( &ts, NULL );
108
109   loop = 0;
110
111   while( LFDS710_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors,lasue) )
112   {
113     lp = LFDS710_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
114
115     // TRD : first fet of threads (poppers)
116     (tpts+loop)->fs = &fs;
117     (tpts+loop)->number_elements_per_thread = number_elements_per_thread;
118     lfds710_freelist_init_valid_on_current_logical_core( &(tpts+loop)->fs_thread_local, NULL, 0, NULL );
119     libtest_threadset_add_thread( &ts, &pts[loop], lp, thread_popping_and_pushing_start_popping, &tpts[loop] );
120
121     // TRD : fecond fet of threads (pushers - who need elements in their per-thread freelists)
122     (tpts+loop+number_logical_processors)->fs = &fs;
123     (tpts+loop+number_logical_processors)->number_elements_per_thread = number_elements_per_thread;
124     lfds710_freelist_init_valid_on_current_logical_core( &(tpts+loop+number_logical_processors)->fs_thread_local, NULL, 0, NULL );
125     libtest_threadset_add_thread( &ts, &pts[loop+number_logical_processors], lp, thread_popping_and_pushing_start_pushing, &tpts[loop+number_logical_processors] );
126
127     for( subloop = number_elements_per_thread * (number_logical_processors + loop) ; subloop < number_elements_per_thread * (number_logical_processors + loop + 1) ; subloop++ )
128     {
129       LFDS710_FREELIST_SET_VALUE_IN_ELEMENT( (te_array+subloop)->thread_local_fe, (te_array+subloop) );
130       lfds710_freelist_push( &(tpts+loop+number_logical_processors)->fs_thread_local, &(te_array+subloop)->thread_local_fe, NULL );
131     }
132
133     loop++;
134   }
135
136   LFDS710_MISC_BARRIER_STORE;
137
138   lfds710_misc_force_store();
139
140   // TRD : run the test
141   libtest_threadset_run( &ts );
142
143   libtest_threadset_cleanup( &ts );
144
145   // TRD : validate
146   LFDS710_MISC_BARRIER_LOAD;
147
148   vi.min_elements = vi.max_elements = number_elements_per_thread * number_logical_processors * 2;
149
150   lfds710_freelist_query( &fs, LFDS710_FREELIST_QUERY_SINGLETHREADED_VALIDATE, (void *) &vi, (void *) dvs );
151
152   lfds710_freelist_cleanup( &fs, NULL );
153
154   for( loop = 0 ; loop < number_logical_processors ; loop++ )
155   {
156     lfds710_freelist_cleanup( &(tpts+loop)->fs_thread_local, NULL );
157     lfds710_freelist_cleanup( &(tpts+loop+number_logical_processors)->fs_thread_local, NULL );
158   }
159
160   return;
161 }
162
163
164
165
166
167
168 /****************************************************************************/
169 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_popping_and_pushing_start_popping( void *libtest_threadset_per_thread_state )
170 {
171   lfds710_pal_uint_t
172     count;
173
174   struct lfds710_freelist_element
175     *fe;
176
177   struct test_per_thread_state
178     *tpts;
179
180   struct libtest_threadset_per_thread_state
181     *pts;
182
183   time_t
184     start_time;
185
186   LFDS710_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
187
188   LFDS710_PAL_ASSERT( libtest_threadset_per_thread_state != NULL );
189
190   pts = (struct libtest_threadset_per_thread_state *) libtest_threadset_per_thread_state;
191   tpts = LIBTEST_THREADSET_GET_USER_STATE_FROM_PER_THREAD_STATE( *pts );
192
193   libtest_threadset_thread_ready_and_wait( pts );
194
195   start_time = time( NULL );
196
197   while( time(NULL) < start_time + TEST_DURATION_IN_SECONDS )
198   {
199     count = 0;
200
201     while( count < tpts->number_elements_per_thread )
202       if( lfds710_freelist_pop(tpts->fs, &fe, NULL) )
203       {
204         lfds710_freelist_push( &tpts->fs_thread_local, fe, NULL );
205         count++;
206       }
207
208     // TRD : return our local freelist to the main freelist
209     while( lfds710_freelist_pop(&tpts->fs_thread_local, &fe, NULL) )
210       lfds710_freelist_push( tpts->fs, fe, NULL );
211   }
212
213   LFDS710_MISC_BARRIER_STORE;
214
215   lfds710_misc_force_store();
216
217   return LIBSHARED_PAL_THREAD_RETURN_CAST(RETURN_SUCCESS);
218 }
219
220
221
222
223
224 /****************************************************************************/
225 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_popping_and_pushing_start_pushing( void *libtest_threadset_per_thread_state )
226 {
227   lfds710_pal_uint_t
228     count;
229
230   struct lfds710_freelist_element
231     *fe;
232
233   struct test_per_thread_state
234     *tpts;
235
236   struct libtest_threadset_per_thread_state
237     *pts;
238
239   time_t
240     start_time;
241
242   LFDS710_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
243
244   LFDS710_PAL_ASSERT( libtest_threadset_per_thread_state != NULL );
245
246   pts = (struct libtest_threadset_per_thread_state *) libtest_threadset_per_thread_state;
247   tpts = LIBTEST_THREADSET_GET_USER_STATE_FROM_PER_THREAD_STATE( *pts );
248
249   libtest_threadset_thread_ready_and_wait( pts );
250
251   start_time = time( NULL );
252
253   while( time(NULL) < start_time + TEST_DURATION_IN_SECONDS )
254   {
255     // TRD : return our local freelist to the main freelist
256     while( lfds710_freelist_pop(&tpts->fs_thread_local, &fe, NULL) )
257       lfds710_freelist_push( tpts->fs, fe, NULL );
258
259     count = 0;
260
261     while( count < tpts->number_elements_per_thread )
262       if( lfds710_freelist_pop(tpts->fs, &fe, NULL) )
263       {
264         lfds710_freelist_push( &tpts->fs_thread_local, fe, NULL );
265         count++;
266       }
267   }
268
269   // TRD : now push whatever we have in our local freelist
270   while( lfds710_freelist_pop(&tpts->fs_thread_local, &fe, NULL) )
271     lfds710_freelist_push( tpts->fs, fe, NULL );
272
273   LFDS710_MISC_BARRIER_STORE;
274
275   lfds710_misc_force_store();
276
277   return LIBSHARED_PAL_THREAD_RETURN_CAST(RETURN_SUCCESS);
278 }
279