]> pd.if.org Git - liblfds/blob - liblfds/liblfds6.1.0/test/src/test_ringbuffer.c
Initial import (all versions, including the new 7.1.0)
[liblfds] / liblfds / liblfds6.1.0 / test / src / test_ringbuffer.c
1 #include "internal.h"
2
3
4
5
6
7 /****************************************************************************/
8 void test_lfds610_ringbuffer( void )
9 {
10   printf( "\n"
11           "Ringbuffer Tests\n"
12           "================\n" );
13
14   ringbuffer_test_reading();
15   ringbuffer_test_writing();
16   ringbuffer_test_reading_and_writing();
17
18   return;
19 }
20
21
22
23
24
25 /****************************************************************************/
26 void ringbuffer_test_reading( void )
27 {
28   unsigned int
29     loop,
30     cpu_count;
31
32   thread_state_t
33     *thread_handles;
34
35   struct lfds610_ringbuffer_state
36     *rs;
37
38   struct lfds610_freelist_element
39     *fe;
40
41   struct ringbuffer_test_reading_state
42     *rtrs;
43
44   struct lfds610_validation_info
45     vi = { 0, 0 };
46
47   enum lfds610_data_structure_validity
48     dvs[3];
49
50   lfds610_atom_t
51     total_read = 0;
52
53   /* TRD : we create a single ringbuffer
54            with 1,000,000 elements
55            we populate the ringbuffer, where the
56            user data is an incrementing counter
57
58            we create one thread per CPU
59            where each thread busy-works,
60            reading until the ringbuffer is empty
61
62            each thread keeps track of the number of reads it manages
63            and that each user data it reads is greater than the
64            previous user data that was read
65   */
66
67   internal_display_test_name( "Reading" );
68
69   cpu_count = abstraction_cpu_count();
70
71   lfds610_ringbuffer_new( &rs, 1000000, NULL, NULL );
72
73   for( loop = 0 ; loop < 1000000 ; loop++ )
74   {
75     lfds610_ringbuffer_get_write_element( rs, &fe, NULL );
76     lfds610_freelist_set_user_data_in_element( fe, (void *) (lfds610_atom_t) loop );
77     lfds610_ringbuffer_put_write_element( rs, fe );
78   }
79
80   rtrs = malloc( sizeof(struct ringbuffer_test_reading_state) * cpu_count );
81
82   for( loop = 0 ; loop < cpu_count ; loop++ )
83   {
84     (rtrs+loop)->rs = rs;
85     (rtrs+loop)->read_count = 0;
86     (rtrs+loop)->error_flag = LOWERED;
87   }
88
89   thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
90
91   for( loop = 0 ; loop < cpu_count ; loop++ )
92     abstraction_thread_start( &thread_handles[loop], loop, ringbuffer_test_thread_simple_reader, rtrs+loop );
93
94   for( loop = 0 ; loop < cpu_count ; loop++ )
95     abstraction_thread_wait( thread_handles[loop] );
96
97   free( thread_handles );
98
99   lfds610_ringbuffer_query( rs, LFDS610_RINGBUFFER_QUERY_VALIDATE, (void *) &vi, (void *) dvs );
100
101   // TRD : check for raised error flags
102   for( loop = 0 ; loop < cpu_count ; loop++ )
103     if( (rtrs+loop)->error_flag == RAISED )
104       dvs[0] = LFDS610_VALIDITY_INVALID_TEST_DATA;
105
106   // TRD : check thread reads total to 1,000,000
107   for( loop = 0 ; loop < cpu_count ; loop++ )
108     total_read += (rtrs+loop)->read_count;
109
110   if( total_read < 1000000 )
111     dvs[0] = LFDS610_VALIDITY_INVALID_MISSING_ELEMENTS;
112
113   if( total_read > 1000000 )
114     dvs[0] = LFDS610_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
115
116   free( rtrs );
117
118   lfds610_ringbuffer_delete( rs, NULL, NULL );
119
120   internal_display_test_result( 3, "queue", dvs[0], "queue freelist", dvs[1], "freelist", dvs[2] );
121
122   return;
123 }
124
125
126
127
128
129 /****************************************************************************/
130 thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_reader( void *ringbuffer_test_reading_state )
131 {
132   struct ringbuffer_test_reading_state
133     *rtrs;
134
135   struct lfds610_freelist_element
136     *fe;
137
138   lfds610_atom_t
139     *prev_user_data,
140     *user_data;
141
142   assert( ringbuffer_test_reading_state != NULL );
143
144   rtrs = (struct ringbuffer_test_reading_state *) ringbuffer_test_reading_state;
145
146   lfds610_ringbuffer_use( rtrs->rs );
147
148   /* TRD : read an initial element to load a value into prev_user_data
149            it may be (under valgrind for example) that by the time we start
150            there are no elements remaining to read
151   */
152
153   lfds610_ringbuffer_get_read_element( rtrs->rs, &fe );
154   if( fe == NULL )
155     return( (thread_return_t) EXIT_SUCCESS );
156   lfds610_freelist_get_user_data_from_element( fe, (void **) &prev_user_data );
157   lfds610_ringbuffer_put_read_element( rtrs->rs, fe );
158
159   rtrs->read_count++;
160
161   while( lfds610_ringbuffer_get_read_element(rtrs->rs, &fe) )
162   {
163     lfds610_freelist_get_user_data_from_element( fe, (void **) &user_data );
164     lfds610_ringbuffer_put_read_element( rtrs->rs, fe );
165
166     if( user_data <= prev_user_data )
167       rtrs->error_flag = RAISED;
168
169     prev_user_data = user_data;
170
171     rtrs->read_count++;
172   }
173
174   return( (thread_return_t) EXIT_SUCCESS );
175 }
176
177
178
179
180
181 /****************************************************************************/
182 void ringbuffer_test_writing( void )
183 {
184   unsigned int
185     loop,
186     cpu_count;
187
188   thread_state_t
189     *thread_handles;
190
191   struct lfds610_ringbuffer_state
192     *rs;
193
194   struct lfds610_freelist_element
195     *fe;
196
197   struct ringbuffer_test_writing_state
198     *rtws;
199
200   struct lfds610_validation_info
201     vi = { 100000, 100000 };
202
203   enum lfds610_data_structure_validity
204     dvs[3];
205
206   lfds610_atom_t
207     thread,
208     count,
209     user_data,
210     *per_thread_counters;
211
212   /* TRD : we create a single ringbuffer
213            with 100000 elements
214            the ringbuffers starts empty
215
216            we create one thread per CPU
217            where each thread busy-works writing
218            for ten seconds
219
220            the user data in each written element is a combination
221            of the thread number and the counter
222
223            after the threads are complete, we validate by
224            checking the user data counters increment on a per thread
225            basis
226   */
227
228   internal_display_test_name( "Writing (10 seconds)" );
229
230   cpu_count = abstraction_cpu_count();
231
232   lfds610_ringbuffer_new( &rs, 100000, NULL, NULL );
233
234   rtws = malloc( sizeof(struct ringbuffer_test_writing_state) * cpu_count );
235
236   for( loop = 0 ; loop < cpu_count ; loop++ )
237   {
238     (rtws+loop)->rs = rs;
239     (rtws+loop)->write_count = (lfds610_atom_t) loop << (sizeof(lfds610_atom_t)*8-8);
240   }
241
242   thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
243
244   for( loop = 0 ; loop < cpu_count ; loop++ )
245     abstraction_thread_start( &thread_handles[loop], loop, ringbuffer_test_thread_simple_writer, rtws+loop );
246
247   for( loop = 0 ; loop < cpu_count ; loop++ )
248     abstraction_thread_wait( thread_handles[loop] );
249
250   free( thread_handles );
251
252   // TRD : now check results
253   per_thread_counters = malloc( sizeof(lfds610_atom_t) * cpu_count );
254
255   for( loop = 0 ; loop < cpu_count ; loop++ )
256     *(per_thread_counters+loop) = 0;
257
258   lfds610_ringbuffer_query( rs, LFDS610_RINGBUFFER_QUERY_VALIDATE, (void *) &vi, (void *) dvs );
259
260   while( dvs[0] == LFDS610_VALIDITY_VALID and dvs[1] == LFDS610_VALIDITY_VALID and dvs[2] == LFDS610_VALIDITY_VALID and lfds610_ringbuffer_get_read_element(rs, &fe) )
261   {
262     lfds610_freelist_get_user_data_from_element( fe, (void *) &user_data );
263
264     thread = user_data >> (sizeof(lfds610_atom_t)*8-8);
265     count = (user_data << 8) >> 8;
266
267     if( thread >= cpu_count )
268     {
269       dvs[0] = LFDS610_VALIDITY_INVALID_TEST_DATA;
270       lfds610_ringbuffer_put_read_element( rs, fe );
271       break;
272     }
273
274     if( per_thread_counters[thread] == 0 )
275       per_thread_counters[thread] = count;
276
277     if( count < per_thread_counters[thread] )
278       dvs[0] = LFDS610_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
279
280     if( count >= per_thread_counters[thread] )
281       per_thread_counters[thread] = count+1;
282
283     lfds610_ringbuffer_put_read_element( rs, fe );
284   }
285
286   free( per_thread_counters );
287
288   free( rtws );
289
290   lfds610_ringbuffer_delete( rs, NULL, NULL );
291
292   internal_display_test_result( 3, "queue", dvs[0], "queue freelist", dvs[1], "freelist", dvs[2] );
293
294   return;
295 }
296
297
298
299
300
301 /****************************************************************************/
302 thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_writer( void *ringbuffer_test_writing_state )
303 {
304   struct ringbuffer_test_writing_state
305     *rtws;
306
307   struct lfds610_freelist_element
308     *fe;
309
310   time_t
311     start_time;
312
313   assert( ringbuffer_test_writing_state != NULL );
314
315   rtws = (struct ringbuffer_test_writing_state *) ringbuffer_test_writing_state;
316
317   lfds610_ringbuffer_use( rtws->rs );
318
319   time( &start_time );
320
321   while( time(NULL) < start_time + 10 )
322   {
323     lfds610_ringbuffer_get_write_element( rtws->rs, &fe, NULL );
324     lfds610_freelist_set_user_data_in_element( fe, (void *) (lfds610_atom_t) (rtws->write_count++) );
325     lfds610_ringbuffer_put_write_element( rtws->rs, fe );
326   }
327
328   return( (thread_return_t) EXIT_SUCCESS );
329 }
330
331
332
333
334
335 /****************************************************************************/
336 void ringbuffer_test_reading_and_writing( void )
337 {
338   unsigned int
339     loop,
340     subloop,
341     cpu_count;
342
343   thread_state_t
344     *thread_handles;
345
346   struct lfds610_ringbuffer_state
347     *rs;
348
349   struct ringbuffer_test_reading_and_writing_state
350     *rtrws;
351
352   struct lfds610_validation_info
353     vi = { 0, 0 };
354
355   enum lfds610_data_structure_validity
356     dvs[3];
357
358   /* TRD : we create a single ringbuffer
359            with 100000 elements
360            the ringbuffers starts empty
361
362            we create one thread per CPU
363            where each thread busy-works writing
364            and then immediately reading
365            for ten seconds
366
367            the user data in each written element is a combination
368            of the thread number and the counter
369
370            while a thread runs, it keeps track of the
371            counters for the other threads and throws an error
372            if it sees the number stay the same or decrease
373   */
374
375   internal_display_test_name( "Reading and writing (10 seconds)" );
376
377   cpu_count = abstraction_cpu_count();
378
379   lfds610_ringbuffer_new( &rs, 100000, NULL, NULL );
380
381   rtrws = malloc( sizeof(struct ringbuffer_test_reading_and_writing_state) * cpu_count );
382
383   for( loop = 0 ; loop < cpu_count ; loop++ )
384   {
385     (rtrws+loop)->rs = rs;
386     (rtrws+loop)->counter = (lfds610_atom_t) loop << (sizeof(lfds610_atom_t)*8-8);
387     (rtrws+loop)->cpu_count = cpu_count;
388     (rtrws+loop)->error_flag = LOWERED;
389     (rtrws+loop)->per_thread_counters = malloc( sizeof(lfds610_atom_t) * cpu_count );
390
391     for( subloop = 0 ; subloop < cpu_count ; subloop++ )
392       *((rtrws+loop)->per_thread_counters+subloop) = 0;
393   }
394
395   thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
396
397   for( loop = 0 ; loop < cpu_count ; loop++ )
398     abstraction_thread_start( &thread_handles[loop], loop, ringbuffer_test_thread_reader_writer, rtrws+loop );
399
400   for( loop = 0 ; loop < cpu_count ; loop++ )
401     abstraction_thread_wait( thread_handles[loop] );
402
403   free( thread_handles );
404
405   lfds610_ringbuffer_query( rs, LFDS610_RINGBUFFER_QUERY_VALIDATE, (void *) &vi, (void *) dvs );
406
407   for( loop = 0 ; loop < cpu_count ; loop++ )
408     if( (rtrws+loop)->error_flag == RAISED )
409       dvs[0] = LFDS610_VALIDITY_INVALID_TEST_DATA;
410
411   for( loop = 0 ; loop < cpu_count ; loop++ )
412     free( (rtrws+loop)->per_thread_counters );
413
414   free( rtrws );
415
416   lfds610_ringbuffer_delete( rs, NULL, NULL );
417
418   internal_display_test_result( 3, "queue", dvs[0], "queue freelist", dvs[1], "freelist", dvs[2] );
419
420   return;
421 }
422
423
424
425
426
427 /****************************************************************************/
428 thread_return_t CALLING_CONVENTION ringbuffer_test_thread_reader_writer( void *ringbuffer_test_reading_and_writing_state )
429 {
430   struct ringbuffer_test_reading_and_writing_state
431     *rtrws;
432
433   struct lfds610_freelist_element
434     *fe;
435
436   lfds610_atom_t
437     user_data,
438     thread,
439     count;
440
441   time_t
442     start_time;
443
444   assert( ringbuffer_test_reading_and_writing_state != NULL );
445
446   rtrws = (struct ringbuffer_test_reading_and_writing_state *) ringbuffer_test_reading_and_writing_state;
447
448   lfds610_ringbuffer_use( rtrws->rs );
449
450   time( &start_time );
451
452   while( time(NULL) < start_time + 10 )
453   {
454     lfds610_ringbuffer_get_write_element( rtrws->rs, &fe, NULL );
455     lfds610_freelist_set_user_data_in_element( fe, (void *) (lfds610_atom_t) (rtrws->counter++) );
456     lfds610_ringbuffer_put_write_element( rtrws->rs, fe );
457
458     lfds610_ringbuffer_get_read_element( rtrws->rs, &fe );
459     lfds610_freelist_get_user_data_from_element( fe, (void *) &user_data );
460
461     thread = user_data >> (sizeof(lfds610_atom_t)*8-8);
462     count = (user_data << 8) >> 8;
463
464     if( thread >= rtrws->cpu_count )
465       rtrws->error_flag = RAISED;
466     else
467     {
468       if( count < rtrws->per_thread_counters[thread] )
469         rtrws->error_flag = RAISED;
470
471       if( count >= rtrws->per_thread_counters[thread] )
472         rtrws->per_thread_counters[thread] = count+1;
473     }
474
475     lfds610_ringbuffer_put_read_element( rtrws->rs, fe );
476   }
477
478   return( (thread_return_t) EXIT_SUCCESS );
479 }
480