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