]> pd.if.org Git - liblfds/blob - liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_stack_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_pushing.c
1 /***** includes *****/
2 #include "libtest_tests_internal.h"
3
4 /***** structs *****/
5 struct test_per_thread_state
6 {
7   lfds710_pal_uint_t
8     number_elements_per_thread,
9     thread_number;
10
11   struct lfds710_stack_state
12     *ss;
13
14   struct test_element
15     *te_array;
16 };
17
18 struct test_element
19 {
20   struct lfds710_stack_element
21     se;
22
23   lfds710_pal_uint_t
24     datum,
25     thread_number;
26 };
27
28 /***** private prototypes *****/
29 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_pushing( void *libtest_threadset_per_thread_state );
30
31
32
33
34
35 /****************************************************************************/
36 void libtest_tests_stack_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 = 0,
40     number_elements,
41     number_elements_per_thread,
42     number_logical_processors,
43     *per_thread_counters;
44
45   struct lfds710_list_asu_element
46     *lasue = NULL;
47
48   struct lfds710_stack_element
49     *se;
50
51   struct lfds710_stack_state
52     ss;
53
54   struct lfds710_misc_validation_info
55     vi;
56
57   struct libtest_logical_processor
58     *lp;
59
60   struct libtest_threadset_per_thread_state
61     *pts;
62
63   struct libtest_threadset_state
64     ts;
65
66   struct test_element
67     *te,
68     *te_array;
69
70   struct test_per_thread_state
71     *tpts;
72
73   LFDS710_PAL_ASSERT( list_of_logical_processors != NULL );
74   LFDS710_PAL_ASSERT( ms != NULL );
75   LFDS710_PAL_ASSERT( dvs != NULL );
76
77   /* TRD : we create an empty stack
78
79            we then create one thread per CPU, where each thread
80            pushes 100,000 elements each as quickly as possible to the stack
81
82            the data pushed is a counter and a thread ID
83
84            the threads exit when the stack is full
85
86            we then validate the stack;
87
88            checking that the counts increment on a per unique ID basis
89            and that the number of elements we pop equals 100,000 per thread
90            (since each element has an incrementing counter which is
91             unique on a per unique ID basis, we can know we didn't lose
92             any elements)
93   */
94
95   *dvs = LFDS710_MISC_VALIDITY_VALID;
96
97   // TRD : allocate
98   lfds710_list_asu_query( list_of_logical_processors, LFDS710_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
99   tpts = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct test_per_thread_state) * number_logical_processors, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
100   pts = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct libtest_threadset_per_thread_state) * number_logical_processors, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
101   per_thread_counters = libshared_memory_alloc_from_unknown_node( ms, sizeof(lfds710_pal_uint_t) * number_logical_processors, sizeof(lfds710_pal_uint_t) );
102   te_array = libshared_memory_alloc_largest_possible_array_from_unknown_node( ms, sizeof(struct test_element), LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES, &number_elements );
103
104   number_elements_per_thread = number_elements / number_logical_processors;
105
106   // TRD : the main stack
107   lfds710_stack_init_valid_on_current_logical_core( &ss, NULL );
108
109   libtest_threadset_init( &ts, NULL );
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     (tpts+loop)->ss = &ss;
116     (tpts+loop)->thread_number = loop;
117     (tpts+loop)->number_elements_per_thread = number_elements_per_thread;
118     (tpts+loop)->te_array = te_array + loop * number_elements_per_thread;
119
120     libtest_threadset_add_thread( &ts, &pts[loop], lp, thread_pushing, &tpts[loop] );
121
122     loop++;
123   }
124
125   LFDS710_MISC_BARRIER_STORE;
126
127   lfds710_misc_force_store();
128
129   // TRD : run the test
130   libtest_threadset_run( &ts );
131
132   libtest_threadset_cleanup( &ts );
133
134   // TRD : validate
135   LFDS710_MISC_BARRIER_LOAD;
136
137   for( loop = 0 ; loop < number_logical_processors ; loop++ )
138     *(per_thread_counters+loop) = number_elements_per_thread - 1;
139
140   vi.min_elements = vi.max_elements = number_elements_per_thread * number_logical_processors;
141
142   lfds710_stack_query( &ss, LFDS710_STACK_QUERY_SINGLETHREADED_VALIDATE, &vi, dvs );
143
144   while( *dvs == LFDS710_MISC_VALIDITY_VALID and lfds710_stack_pop(&ss, &se) )
145   {
146     te = LFDS710_STACK_GET_VALUE_FROM_ELEMENT( *se );
147
148     if( te->thread_number >= number_logical_processors )
149     {
150       *dvs = LFDS710_MISC_VALIDITY_INVALID_TEST_DATA;
151       break;
152     }
153
154     if( te->datum > per_thread_counters[te->thread_number] )
155       *dvs = LFDS710_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
156
157     if( te->datum < per_thread_counters[te->thread_number] )
158       *dvs = LFDS710_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
159
160     if( te->datum == per_thread_counters[te->thread_number] )
161       per_thread_counters[te->thread_number]--;
162   }
163
164   lfds710_stack_cleanup( &ss, NULL );
165
166   return;
167 }
168
169
170
171
172
173 /****************************************************************************/
174 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_pushing( void *libtest_threadset_per_thread_state )
175 {
176   lfds710_pal_uint_t
177     loop;
178
179   struct test_per_thread_state
180     *tpts;
181
182   struct libtest_threadset_per_thread_state
183     *pts;
184
185   LFDS710_MISC_BARRIER_LOAD;
186
187   LFDS710_PAL_ASSERT( libtest_threadset_per_thread_state != NULL );
188
189   pts = (struct libtest_threadset_per_thread_state *) libtest_threadset_per_thread_state;
190
191   tpts = LIBTEST_THREADSET_GET_USER_STATE_FROM_PER_THREAD_STATE( *pts );
192
193   for( loop = 0 ; loop < tpts->number_elements_per_thread ; loop++ )
194   {
195     (tpts->te_array+loop)->thread_number = tpts->thread_number;
196     (tpts->te_array+loop)->datum = loop;
197   }
198
199   libtest_threadset_thread_ready_and_wait( pts );
200
201   for( loop = 0 ; loop < tpts->number_elements_per_thread ; loop++ )
202   {
203     LFDS710_STACK_SET_VALUE_IN_ELEMENT( (tpts->te_array+loop)->se, tpts->te_array+loop );
204     lfds710_stack_push( tpts->ss, &(tpts->te_array+loop)->se );
205   }
206
207   LFDS710_MISC_BARRIER_STORE;
208
209   lfds710_misc_force_store();
210
211   return LIBSHARED_PAL_THREAD_RETURN_CAST(RETURN_SUCCESS);
212 }
213