]> pd.if.org Git - liblfds/blob - liblfds/liblfds7.0.0/test/src/test_lfds700_ringbuffer_writing.c
Initial import (all versions, including the new 7.1.0)
[liblfds] / liblfds / liblfds7.0.0 / test / src / test_lfds700_ringbuffer_writing.c
1 /***** includes *****/
2 #include "internal.h"
3
4 /***** structs *****/
5 struct test_element
6 {
7   lfds700_pal_uint_t
8     thread_number,
9     datum;
10 };
11
12 struct test_state
13 {
14   lfds700_pal_uint_t
15     thread_number,
16     write_count;
17
18   struct test_element
19     te;
20
21   struct lfds700_ringbuffer_state
22     *rs;
23 };
24
25 /***** private prototypes *****/
26 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_simple_writer( void *util_thread_starter_thread_state );
27
28
29
30
31
32 /****************************************************************************/
33 void test_lfds700_ringbuffer_writing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
34 {
35   enum lfds700_misc_validity
36     dvs[2] = { LFDS700_MISC_VALIDITY_VALID, LFDS700_MISC_VALIDITY_VALID };
37
38   lfds700_pal_uint_t
39     loop,
40     number_elements_with_dummy_element,
41     number_elements_without_dummy_element,
42     number_logical_processors,
43     *per_thread_counters;
44
45   test_pal_thread_state_t
46     *thread_handles;
47
48   struct lfds700_list_asu_element
49     *lasue;
50
51   struct lfds700_misc_prng_state
52     ps;
53
54   struct lfds700_ringbuffer_element
55     *re_array;
56
57   struct lfds700_ringbuffer_state
58     rs;
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     *te_array;
72
73   struct test_state
74     *ts;
75
76   assert( list_of_logical_processors != NULL );
77   // TRD : memory_in_megabytes can be any value in its range
78
79   /* TRD : we create a single ringbuffer
80            with n elements
81            we create n test elements
82            which are thread_number/counter pairs
83            init them to safe values
84            and fully populate the ringbuffer
85
86            we create one thread per CPU
87            where each thread busy-works writing
88            for ten seconds; each thread has one extra element
89            which it uses for the first write and after that
90            it uses the element it picks up from overwriting
91
92            the user data in each written element is a combination
93            of the thread number and the counter
94
95            after the threads are complete, we validate by
96            checking the user data counters increment on a per thread
97            basis
98   */
99
100   internal_display_test_name( "Writing (%d seconds)", TEST_DURATION_IN_SECONDS );
101
102   lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
103
104   lfds700_misc_prng_init( &ps );
105
106   number_elements_with_dummy_element = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) + sizeof(struct lfds700_ringbuffer_element) );
107   number_elements_without_dummy_element = number_elements_with_dummy_element - 1;
108
109   vi.min_elements = number_elements_without_dummy_element;
110   vi.max_elements = number_elements_without_dummy_element;
111
112   re_array = util_aligned_malloc( sizeof(struct lfds700_ringbuffer_element) * number_elements_with_dummy_element, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
113
114   lfds700_ringbuffer_init_valid_on_current_logical_core( &rs, re_array, number_elements_with_dummy_element, &ps, NULL );
115
116   te_array = util_malloc_wrapper( sizeof(struct lfds700_ringbuffer_element) * number_elements_without_dummy_element );
117
118   // TRD : init the test elements and write them into the ringbuffer
119   for( loop = 0 ; loop < number_elements_without_dummy_element ; loop++ )
120   {
121     te_array[loop].thread_number = 0;
122     te_array[loop].datum = 0;
123     lfds700_ringbuffer_write( &rs, NULL, &te_array[loop], NULL, NULL, NULL, &ps );
124   }
125
126   ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
127
128   for( loop = 0 ; loop < number_logical_processors ; loop++ )
129   {
130     (ts+loop)->rs = &rs;
131     (ts+loop)->thread_number = loop;
132     (ts+loop)->write_count = 0;
133   }
134
135   thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
136
137   util_thread_starter_new( &tts, number_logical_processors );
138
139   LFDS700_MISC_BARRIER_STORE;
140
141   lfds700_misc_force_store();
142
143   loop = 0;
144   lasue = NULL;
145
146   while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
147   {
148     lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
149     util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_simple_writer, ts+loop );
150     loop++;
151   }
152
153   util_thread_starter_run( tts );
154
155   for( loop = 0 ; loop < number_logical_processors ; loop++ )
156     test_pal_thread_wait( thread_handles[loop] );
157
158   util_thread_starter_delete( tts );
159
160   free( thread_handles );
161
162   LFDS700_MISC_BARRIER_LOAD;
163
164   // TRD : now check results
165   per_thread_counters = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_logical_processors );
166
167   for( loop = 0 ; loop < number_logical_processors ; loop++ )
168     *(per_thread_counters+loop) = 0;
169
170   lfds700_ringbuffer_query( &rs, LFDS700_RINGBUFFER_QUERY_SINGLETHREADED_VALIDATE, &vi, dvs );
171
172   while( dvs[0] == LFDS700_MISC_VALIDITY_VALID and dvs[1] == LFDS700_MISC_VALIDITY_VALID and lfds700_ringbuffer_read(&rs, NULL, (void **) &te, &ps) )
173   {
174     if( te->thread_number >= number_logical_processors )
175     {
176       dvs[0] = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
177       break;
178     }
179
180     if( per_thread_counters[te->thread_number] == 0 )
181       per_thread_counters[te->thread_number] = te->datum;
182
183     if( te->datum < per_thread_counters[te->thread_number] )
184       dvs[0] = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
185
186     if( te->datum >= per_thread_counters[te->thread_number] )
187       per_thread_counters[te->thread_number] = te->datum+1;
188   }
189
190   free( per_thread_counters );
191
192   lfds700_ringbuffer_cleanup( &rs, NULL );
193
194   free( ts );
195
196   util_aligned_free( re_array );
197
198   free( te_array );
199
200   internal_display_test_result( 2, "queue", dvs[0], "freelist", dvs[1] );
201
202   return;
203 }
204
205
206
207
208
209 /****************************************************************************/
210 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_simple_writer( void *util_thread_starter_thread_state )
211 {
212   enum lfds700_misc_flag
213     overwrite_occurred_flag;
214
215   lfds700_pal_uint_t
216     time_loop = 0;
217
218   struct lfds700_misc_prng_state
219     ps;
220
221   struct test_element
222     *te;
223
224   struct test_state
225     *ts;
226
227   struct util_thread_starter_thread_state
228     *tsts;
229
230   time_t
231     current_time,
232     start_time;
233
234   LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
235
236   assert( util_thread_starter_thread_state != NULL );
237
238   tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
239   ts = (struct test_state *) tsts->thread_user_state;
240
241   lfds700_misc_prng_init( &ps );
242
243   ts->te.thread_number = 0;
244   ts->te.datum = 0;
245
246   lfds700_ringbuffer_write( ts->rs, NULL, &ts->te, &overwrite_occurred_flag, NULL, (void **) &te, &ps );
247
248   util_thread_starter_ready_and_wait( tsts );
249
250   current_time = start_time = time( NULL );
251
252   while( current_time < start_time + TEST_DURATION_IN_SECONDS )
253   {
254     te->thread_number = ts->thread_number;
255     te->datum = ts->write_count++;
256
257     lfds700_ringbuffer_write( ts->rs, NULL, te, &overwrite_occurred_flag, NULL, (void **) &te, &ps );
258
259     if( time_loop++ == TIME_LOOP_COUNT )
260     {
261       time_loop = 0;
262       time( &current_time );
263     }
264   }
265
266   LFDS700_MISC_BARRIER_STORE;
267
268   lfds700_misc_force_store();
269
270   return( (test_pal_thread_return_t) EXIT_SUCCESS );
271 }
272