]> pd.if.org Git - liblfds/blob - liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_freelist_without_ea_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_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_freelist_state
12     *fs;
13
14   struct test_element
15     *te_array;
16 };
17
18 struct test_element
19 {
20   struct lfds710_freelist_element
21     fe;
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_freelist_without_ea_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_freelist_element
49     *fe;
50
51   struct lfds710_freelist_state
52     fs;
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 freelist
78
79            we then create one thread per CPU, where each thread
80            pushes 100,000 elements each as quickly as possible to the freelist
81
82            the data pushed is a counter and a thread ID
83
84            the threads exit when the freelist is full
85
86            we then validate the freelist;
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 lofe
92             any elements)
93   */
94
95   *dvs = LFDS710_MISC_VALIDITY_VALID;
96
97   lfds710_list_asu_query( list_of_logical_processors, LFDS710_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
98
99   // TRD : allocate
100   tpts = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct test_per_thread_state) * number_logical_processors, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
101   pts = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct libtest_threadset_per_thread_state) * number_logical_processors, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
102   per_thread_counters = libshared_memory_alloc_from_unknown_node( ms, sizeof(lfds710_pal_uint_t) * number_logical_processors, sizeof(lfds710_pal_uint_t) );
103   te_array = libshared_memory_alloc_largest_possible_array_from_unknown_node( ms, sizeof(struct test_element), LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES, &number_elements );
104
105   number_elements_per_thread = number_elements / number_logical_processors;
106
107   // TRD : the main freelist
108   lfds710_freelist_init_valid_on_current_logical_core( &fs, NULL, 0, NULL );
109
110   libtest_threadset_init( &ts, NULL );
111
112   while( LFDS710_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
113   {
114     lp = LFDS710_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
115
116     (tpts+loop)->fs = &fs;
117     (tpts+loop)->thread_number = loop;
118     (tpts+loop)->number_elements_per_thread = number_elements_per_thread;
119     (tpts+loop)->te_array = te_array + loop * number_elements_per_thread;
120
121     libtest_threadset_add_thread( &ts, &pts[loop], lp, thread_pushing, &tpts[loop] );
122
123     loop++;
124   }
125
126   LFDS710_MISC_BARRIER_STORE;
127
128   lfds710_misc_force_store();
129
130   // TRD : run the test
131   libtest_threadset_run( &ts );
132
133   libtest_threadset_cleanup( &ts );
134
135   // TRD : validate
136   LFDS710_MISC_BARRIER_LOAD;
137
138   /* TRD : no EA flush - it consists of the first elements
139            and flushing would break the order validation check below
140   */
141
142   for( loop = 0 ; loop < number_logical_processors ; loop++ )
143     *(per_thread_counters+loop) = number_elements_per_thread - 1;
144
145   vi.min_elements = vi.max_elements = number_elements_per_thread * number_logical_processors;
146
147   lfds710_freelist_query( &fs, LFDS710_FREELIST_QUERY_SINGLETHREADED_VALIDATE, &vi, dvs );
148
149   /* TRD : the elimination array will be populates with a random set of freelist elements
150            we expect then up to that many elements to be out of order
151   */
152
153   while( *dvs == LFDS710_MISC_VALIDITY_VALID and lfds710_freelist_pop(&fs, &fe, NULL) )
154   {
155     te = LFDS710_FREELIST_GET_VALUE_FROM_ELEMENT( *fe );
156
157     if( te->thread_number >= number_logical_processors )
158     {
159       *dvs = LFDS710_MISC_VALIDITY_INVALID_TEST_DATA;
160       break;
161     }
162
163     if( te->datum > per_thread_counters[te->thread_number] )
164       *dvs = LFDS710_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
165
166     if( te->datum < per_thread_counters[te->thread_number] )
167       *dvs = LFDS710_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
168
169     if( te->datum == per_thread_counters[te->thread_number] )
170       per_thread_counters[te->thread_number]--;
171   }
172
173   lfds710_freelist_cleanup( &fs, NULL );
174
175   return;
176 }
177
178
179
180
181
182 /****************************************************************************/
183 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_pushing( void *libtest_threadset_per_thread_state )
184 {
185   lfds710_pal_uint_t
186     loop;
187
188   struct test_per_thread_state
189     *tpts;
190
191   struct libtest_threadset_per_thread_state
192     *pts;
193
194   LFDS710_MISC_BARRIER_LOAD;
195
196   LFDS710_PAL_ASSERT( libtest_threadset_per_thread_state != NULL );
197
198   pts = (struct libtest_threadset_per_thread_state *) libtest_threadset_per_thread_state;
199
200   tpts = LIBTEST_THREADSET_GET_USER_STATE_FROM_PER_THREAD_STATE( *pts );
201
202   for( loop = 0 ; loop < tpts->number_elements_per_thread ; loop++ )
203   {
204     (tpts->te_array+loop)->thread_number = tpts->thread_number;
205     (tpts->te_array+loop)->datum = loop;
206   }
207
208   libtest_threadset_thread_ready_and_wait( pts );
209
210   for( loop = 0 ; loop < tpts->number_elements_per_thread ; loop++ )
211   {
212     LFDS710_FREELIST_SET_VALUE_IN_ELEMENT( (tpts->te_array+loop)->fe, tpts->te_array+loop );
213     lfds710_freelist_push( tpts->fs, &(tpts->te_array+loop)->fe, NULL );
214   }
215
216   LFDS710_MISC_BARRIER_STORE;
217
218   lfds710_misc_force_store();
219
220   return LIBSHARED_PAL_THREAD_RETURN_CAST(RETURN_SUCCESS);
221 }
222