]> pd.if.org Git - liblfds/blob - liblfds/liblfds7.0.0/test/src/test_lfds700_queue_enqueuing.c
Initial import (all versions, including the new 7.1.0)
[liblfds] / liblfds / liblfds7.0.0 / test / src / test_lfds700_queue_enqueuing.c
1 /***** includes *****/
2 #include "internal.h"
3
4 /***** structs *****/
5 struct test_state
6 {
7   lfds700_pal_uint_t
8     number_elements,
9     thread_number;
10
11   struct lfds700_queue_state
12     *qs;
13
14   struct test_element
15     *te_array;
16 };
17
18 struct test_element
19 {
20   struct lfds700_queue_element
21     qe;
22
23   lfds700_pal_uint_t
24     counter,
25     thread_number;
26 };
27
28 /***** private prototypes *****/
29 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_simple_enqueuer( void *util_thread_starter_thread_state );
30
31
32
33
34
35 /****************************************************************************/
36 void test_lfds700_queue_enqueuing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
37 {
38   enum lfds700_misc_validity
39     dvs = LFDS700_MISC_VALIDITY_VALID;
40
41   lfds700_pal_uint_t
42     *per_thread_counters,
43     loop,
44     number_elements,
45     number_logical_processors;
46
47   struct lfds700_list_asu_element
48     *lasue;
49
50   struct lfds700_misc_prng_state
51     ps;
52
53   struct lfds700_queue_element
54     dummy_qe,
55     *qe;
56
57   struct lfds700_queue_state
58     qs;
59
60   struct lfds700_misc_validation_info
61     vi;
62
63   struct test_pal_logical_processor
64     *lp;
65
66   struct util_thread_starter_state
67     *tts;
68
69   struct test_element
70     *te;
71
72   struct test_state
73     *ts;
74
75   test_pal_thread_state_t
76     *thread_handles;
77
78   assert( list_of_logical_processors != NULL );
79   // TRD : memory_in_megabytes can be any value in its range
80
81   /* TRD : create an empty queue
82            then run one thread per CPU
83            where each thread busy-works, enqueuing elements from a freelist (one local freelist per thread)
84            until 100000 elements are enqueued, per thread
85            each element's void pointer of user data is a struct containing thread number and element number
86            where element_number is a thread-local counter starting at 0
87
88            when we're done, we check that all the elements are present
89            and increment on a per-thread basis
90   */
91
92   internal_display_test_name( "Enqueuing" );
93
94   lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
95
96   lfds700_misc_prng_init( &ps );
97
98   number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) * number_logical_processors );
99
100   lfds700_queue_init_valid_on_current_logical_core( &qs, &dummy_qe, &ps, NULL );
101
102   ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
103
104   for( loop = 0 ; loop < number_logical_processors ; loop++ )
105   {
106     (ts+loop)->qs = &qs;
107     (ts+loop)->thread_number = loop;
108     (ts+loop)->number_elements = number_elements;
109   }
110
111   thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
112
113   util_thread_starter_new( &tts, number_logical_processors );
114
115   LFDS700_MISC_BARRIER_STORE;
116
117   lfds700_misc_force_store();
118
119   loop = 0;
120   lasue = NULL;
121
122   while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
123   {
124     lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
125     util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_simple_enqueuer, ts+loop );
126     loop++;
127   }
128
129   util_thread_starter_run( tts );
130
131   for( loop = 0 ; loop < number_logical_processors ; loop++ )
132     test_pal_thread_wait( thread_handles[loop] );
133
134   util_thread_starter_delete( tts );
135
136   free( thread_handles );
137
138   LFDS700_MISC_BARRIER_LOAD;
139
140   /* TRD : first, validate the queue
141
142            then dequeue
143            we expect to find element numbers increment on a per thread basis
144   */
145
146   vi.min_elements = vi.max_elements = number_elements * number_logical_processors;
147
148   lfds700_queue_query( &qs, LFDS700_QUEUE_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
149
150   per_thread_counters = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_logical_processors );
151
152   for( loop = 0 ; loop < number_logical_processors ; loop++ )
153     *(per_thread_counters+loop) = 0;
154
155   while( dvs == LFDS700_MISC_VALIDITY_VALID and lfds700_queue_dequeue(&qs, &qe, &ps) )
156   {
157     te = LFDS700_QUEUE_GET_VALUE_FROM_ELEMENT( *qe );
158
159     if( te->thread_number >= number_logical_processors )
160     {
161       dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
162       break;
163     }
164
165     if( te->counter > per_thread_counters[te->thread_number] )
166       dvs = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
167
168     if( te->counter < per_thread_counters[te->thread_number] )
169       dvs = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
170
171     if( te->counter == per_thread_counters[te->thread_number] )
172       per_thread_counters[te->thread_number]++;
173   }
174
175   free( per_thread_counters );
176
177   for( loop = 0 ; loop < number_logical_processors ; loop++ )
178     util_aligned_free( (ts+loop)->te_array );
179
180   free( ts );
181
182   lfds700_queue_cleanup( &qs, NULL );
183
184   internal_display_test_result( 1, "queue", dvs );
185
186   return;
187 }
188
189
190
191
192
193 /****************************************************************************/
194 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_simple_enqueuer( void *util_thread_starter_thread_state )
195 {
196   lfds700_pal_uint_t
197     loop;
198
199   struct lfds700_misc_prng_state
200     ps;
201
202   struct test_state
203     *ts;
204
205   struct util_thread_starter_thread_state
206     *tsts;
207
208   LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
209
210   assert( util_thread_starter_thread_state != NULL );
211
212   tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
213   ts = (struct test_state *) tsts->thread_user_state;
214
215   lfds700_misc_prng_init( &ps );
216
217   ts->te_array = util_aligned_malloc( sizeof(struct test_element) * ts->number_elements, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
218
219   for( loop = 0 ; loop < ts->number_elements ; loop++ )
220   {
221     (ts->te_array+loop)->thread_number = ts->thread_number;
222     (ts->te_array+loop)->counter = loop;
223   }
224
225   util_thread_starter_ready_and_wait( tsts );
226
227   for( loop = 0 ; loop < ts->number_elements ; loop++ )
228   {
229     LFDS700_QUEUE_SET_VALUE_IN_ELEMENT( (ts->te_array+loop)->qe, ts->te_array+loop );
230     lfds700_queue_enqueue( ts->qs, &(ts->te_array+loop)->qe, &ps );
231   }
232
233   LFDS700_MISC_BARRIER_STORE;
234
235   lfds700_misc_force_store();
236
237   return( (test_pal_thread_return_t) EXIT_SUCCESS );
238 }
239