]> pd.if.org Git - liblfds/blob - liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_freelist_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_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 lfds710_prng_st_state
15     psts;
16
17   struct test_element
18     *te_array;
19 };
20
21 struct test_element
22 {
23   struct lfds710_freelist_element
24     fe;
25
26   lfds710_pal_uint_t
27     datum,
28     thread_number;
29 };
30
31 /***** private prototypes *****/
32 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_pushing( void *libtest_threadset_per_thread_state );
33
34
35
36
37
38 /****************************************************************************/
39 void libtest_tests_freelist_ea_pushing( struct lfds710_list_asu_state *list_of_logical_processors, struct libshared_memory_state *ms, enum lfds710_misc_validity *dvs )
40 {
41   lfds710_pal_uint_t
42     loop = 0,
43     number_elements,
44     number_elements_per_thread,
45     number_logical_processors,
46     random_value,
47     smallest_power_of_two_larger_than_or_equal_to_number_logical_processors = 2,
48     temp_number_logical_processors;
49
50   struct lfds710_freelist_element * volatile
51     (*ea)[LFDS710_FREELIST_ELIMINATION_ARRAY_ELEMENT_SIZE_IN_FREELIST_ELEMENTS];
52
53   struct lfds710_list_asu_element
54     *lasue = NULL;
55
56   struct lfds710_freelist_state
57     fs;
58
59   struct lfds710_misc_validation_info
60     vi;
61
62   struct lfds710_prng_st_state
63     psts;
64
65   struct libtest_logical_processor
66     *lp;
67
68   struct libtest_threadset_per_thread_state
69     *pts;
70
71   struct libtest_threadset_state
72     ts;
73
74   struct test_element
75     *te_array;
76
77   struct test_per_thread_state
78     *tpts;
79
80   LFDS710_PAL_ASSERT( list_of_logical_processors != NULL );
81   LFDS710_PAL_ASSERT( ms != NULL );
82   LFDS710_PAL_ASSERT( dvs != NULL );
83
84   /* TRD : we create an empty freelist
85
86            we then create one thread per CPU, where each thread
87            pushes 100,000 elements each as quickly as possible to the freelist
88
89            the data pushed is a counter and a thread ID
90
91            the threads exit when the freelist is full
92
93            we then validate the freelist;
94
95            checking that the counts increment on a per unique ID basis
96            and that the number of elements we pop equals 100,000 per thread
97            (since each element has an incrementing counter which is
98             unique on a per unique ID basis, we can know we didn't lofe
99             any elements)
100   */
101
102   *dvs = LFDS710_MISC_VALIDITY_VALID;
103
104   lfds710_prng_st_init( &psts, LFDS710_PRNG_SEED );
105
106   lfds710_list_asu_query( list_of_logical_processors, LFDS710_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
107
108   temp_number_logical_processors = number_logical_processors >> 2;
109   while( temp_number_logical_processors != 0 )
110   {
111     temp_number_logical_processors >>= 1;
112     smallest_power_of_two_larger_than_or_equal_to_number_logical_processors <<= 1;
113   }
114
115   // TRD : allocate
116   tpts = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct test_per_thread_state) * number_logical_processors, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
117   pts = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct libtest_threadset_per_thread_state) * number_logical_processors, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
118   ea = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct lfds710_freelist_element *) * LFDS710_FREELIST_ELIMINATION_ARRAY_ELEMENT_SIZE_IN_FREELIST_ELEMENTS * smallest_power_of_two_larger_than_or_equal_to_number_logical_processors, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
119   te_array = libshared_memory_alloc_largest_possible_array_from_unknown_node( ms, sizeof(struct test_element), LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES, &number_elements );
120
121   number_elements_per_thread = number_elements / number_logical_processors;
122
123   // TRD : the main freelist
124   lfds710_freelist_init_valid_on_current_logical_core( &fs, ea, smallest_power_of_two_larger_than_or_equal_to_number_logical_processors, NULL );
125
126   libtest_threadset_init( &ts, NULL );
127
128   while( LFDS710_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
129   {
130     lp = LFDS710_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
131
132     (tpts+loop)->fs = &fs;
133     (tpts+loop)->thread_number = loop;
134     (tpts+loop)->number_elements_per_thread = number_elements_per_thread;
135     (tpts+loop)->te_array = te_array + loop * number_elements_per_thread;
136     LFDS710_PRNG_ST_GENERATE( psts, random_value );
137     LFDS710_PRNG_ST_MIXING_FUNCTION( random_value );
138     lfds710_prng_st_init( &(tpts+loop)->psts, random_value );
139
140     libtest_threadset_add_thread( &ts, &pts[loop], lp, thread_pushing, &tpts[loop] );
141
142     loop++;
143   }
144
145   LFDS710_MISC_BARRIER_STORE;
146
147   lfds710_misc_force_store();
148
149   // TRD : run the test
150   libtest_threadset_run( &ts );
151
152   libtest_threadset_cleanup( &ts );
153
154   // TRD : validate
155   LFDS710_MISC_BARRIER_LOAD;
156
157   vi.min_elements = vi.max_elements = number_elements_per_thread * number_logical_processors;
158
159   lfds710_freelist_query( &fs, LFDS710_FREELIST_QUERY_SINGLETHREADED_VALIDATE, &vi, dvs );
160
161   lfds710_freelist_cleanup( &fs, NULL );
162
163   return;
164 }
165
166
167
168
169
170 /****************************************************************************/
171 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_pushing( void *libtest_threadset_per_thread_state )
172 {
173   lfds710_pal_uint_t
174     loop;
175
176   struct test_per_thread_state
177     *tpts;
178
179   struct libtest_threadset_per_thread_state
180     *pts;
181
182   LFDS710_MISC_BARRIER_LOAD;
183
184   LFDS710_PAL_ASSERT( libtest_threadset_per_thread_state != NULL );
185
186   pts = (struct libtest_threadset_per_thread_state *) libtest_threadset_per_thread_state;
187
188   tpts = LIBTEST_THREADSET_GET_USER_STATE_FROM_PER_THREAD_STATE( *pts );
189
190   for( loop = 0 ; loop < tpts->number_elements_per_thread ; loop++ )
191   {
192     (tpts->te_array+loop)->thread_number = tpts->thread_number;
193     (tpts->te_array+loop)->datum = loop;
194   }
195
196   libtest_threadset_thread_ready_and_wait( pts );
197
198   for( loop = 0 ; loop < tpts->number_elements_per_thread ; loop++ )
199   {
200     LFDS710_FREELIST_SET_VALUE_IN_ELEMENT( (tpts->te_array+loop)->fe, tpts->te_array+loop );
201     lfds710_freelist_push( tpts->fs, &(tpts->te_array+loop)->fe, &tpts->psts );
202   }
203
204   LFDS710_MISC_BARRIER_STORE;
205
206   lfds710_misc_force_store();
207
208   return LIBSHARED_PAL_THREAD_RETURN_CAST(RETURN_SUCCESS);
209 }
210