]> pd.if.org Git - liblfds/blob - liblfds/liblfds6.0.0/test/src/test_ringbuffer.c
Initial import (all versions, including the new 7.1.0)
[liblfds] / liblfds / liblfds6.0.0 / test / src / test_ringbuffer.c
1 #include "internal.h"
2
3
4
5
6
7 /****************************************************************************/
8 void test_lfds600_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 lfds600_ringbuffer_state
36     *rs;
37
38   struct lfds600_freelist_element
39     *fe;
40
41   struct ringbuffer_test_reading_state
42     *rtrs;
43
44   struct lfds600_validation_info
45     vi = { 0, 0 };
46
47   enum data_structure_validity
48     dvs[3];
49
50   lfds600_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 keep 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   lfds600_ringbuffer_new( &rs, 1000000, NULL, NULL );
72
73   for( loop = 0 ; loop < 1000000 ; loop++ )
74   {
75     lfds600_ringbuffer_get_write_element( rs, &fe, NULL );
76     lfds600_freelist_set_user_data_in_element( fe, (void *) (lfds600_atom_t) loop );
77     lfds600_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   lfds600_ringbuffer_query( rs, LFDS600_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] = 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] = VALIDITY_INVALID_MISSING_ELEMENTS;
112
113   if( total_read > 1000000 )
114     dvs[0] = VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
115
116   free( rtrs );
117
118   lfds600_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 lfds600_freelist_element
136     *fe;
137
138   lfds600_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   lfds600_ringbuffer_get_read_element( rtrs->rs, &fe );
147   lfds600_freelist_get_user_data_from_element( fe, (void **) &prev_user_data );
148   lfds600_ringbuffer_put_read_element( rtrs->rs, fe );
149
150   rtrs->read_count++;
151
152   while( lfds600_ringbuffer_get_read_element(rtrs->rs, &fe) )
153   {
154     lfds600_freelist_get_user_data_from_element( fe, (void **) &user_data );
155     lfds600_ringbuffer_put_read_element( rtrs->rs, fe );
156
157     if( user_data <= prev_user_data )
158       rtrs->error_flag = RAISED;
159
160     prev_user_data = user_data;
161
162     rtrs->read_count++;
163   }
164
165   return( (thread_return_t) EXIT_SUCCESS );
166 }
167
168
169
170
171
172 /****************************************************************************/
173 void ringbuffer_test_writing( void )
174 {
175   unsigned int
176     loop,
177     cpu_count;
178
179   thread_state_t
180     *thread_handles;
181
182   struct lfds600_ringbuffer_state
183     *rs;
184
185   struct lfds600_freelist_element
186     *fe;
187
188   struct ringbuffer_test_writing_state
189     *rtws;
190
191   struct lfds600_validation_info
192     vi = { 100000, 100000 };
193
194   enum data_structure_validity
195     dvs[3];
196
197   lfds600_atom_t
198     thread,
199     count,
200     user_data,
201     *per_thread_counters;
202
203   /* TRD : we create a single ringbuffer
204            with 100000 elements
205            the ringbuffers starts empty
206
207            we create one thread per CPU
208            where each thread busy-works writing
209            for ten seconds
210
211            the user data in each written element is a combination
212            of the thread number and the counter
213
214            after the threads are complete, we validate by
215            checking the user data counters increment on a per thread
216            basis
217   */
218
219   internal_display_test_name( "Writing (10 seconds)" );
220
221   cpu_count = abstraction_cpu_count();
222
223   lfds600_ringbuffer_new( &rs, 100000, NULL, NULL );
224
225   rtws = malloc( sizeof(struct ringbuffer_test_writing_state) * cpu_count );
226
227   for( loop = 0 ; loop < cpu_count ; loop++ )
228   {
229     (rtws+loop)->rs = rs;
230     (rtws+loop)->write_count = (lfds600_atom_t) loop << (sizeof(lfds600_atom_t)*8-8);
231   }
232
233   thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
234
235   for( loop = 0 ; loop < cpu_count ; loop++ )
236     abstraction_thread_start( &thread_handles[loop], loop, ringbuffer_test_thread_simple_writer, rtws+loop );
237
238   for( loop = 0 ; loop < cpu_count ; loop++ )
239     abstraction_thread_wait( thread_handles[loop] );
240
241   free( thread_handles );
242
243   // TRD : now check results
244   per_thread_counters = malloc( sizeof(lfds600_atom_t) * cpu_count );
245
246   for( loop = 0 ; loop < cpu_count ; loop++ )
247     *(per_thread_counters+loop) = 0;
248
249   lfds600_ringbuffer_query( rs, LFDS600_RINGBUFFER_QUERY_VALIDATE, (void *) &vi, (void *) dvs );
250
251   while( dvs[0] == VALIDITY_VALID and dvs[1] == VALIDITY_VALID and dvs[2] == VALIDITY_VALID and lfds600_ringbuffer_get_read_element(rs, &fe) )
252   {
253     lfds600_freelist_get_user_data_from_element( fe, (void *) &user_data );
254
255     thread = user_data >> (sizeof(lfds600_atom_t)*8-8);
256     count = (user_data << 8) >> 8;
257
258     if( thread >= cpu_count )
259     {
260       dvs[0] = VALIDITY_INVALID_TEST_DATA;
261       lfds600_ringbuffer_put_read_element( rs, fe );
262       break;
263     }
264
265     if( per_thread_counters[thread] == 0 )
266       per_thread_counters[thread] = count;
267
268     if( count < per_thread_counters[thread] )
269       dvs[0] = VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
270
271     if( count >= per_thread_counters[thread] )
272       per_thread_counters[thread] = count+1;
273
274     lfds600_ringbuffer_put_read_element( rs, fe );
275   }
276
277   free( per_thread_counters );
278
279   free( rtws );
280
281   lfds600_ringbuffer_delete( rs, NULL, NULL );
282
283   internal_display_test_result( 3, "queue", dvs[0], "queue freelist", dvs[1], "freelist", dvs[2] );
284
285   return;
286 }
287
288
289
290
291
292 /****************************************************************************/
293 thread_return_t CALLING_CONVENTION ringbuffer_test_thread_simple_writer( void *ringbuffer_test_writing_state )
294 {
295   struct ringbuffer_test_writing_state
296     *rtws;
297
298   struct lfds600_freelist_element
299     *fe;
300
301   time_t
302     start_time;
303
304   assert( ringbuffer_test_writing_state != NULL );
305
306   rtws = (struct ringbuffer_test_writing_state *) ringbuffer_test_writing_state;
307
308   time( &start_time );
309
310   while( time(NULL) < start_time + 10 )
311   {
312     lfds600_ringbuffer_get_write_element( rtws->rs, &fe, NULL );
313     lfds600_freelist_set_user_data_in_element( fe, (void *) (lfds600_atom_t) (rtws->write_count++) );
314     lfds600_ringbuffer_put_write_element( rtws->rs, fe );
315   }
316
317   return( (thread_return_t) EXIT_SUCCESS );
318 }
319
320
321
322
323
324 /****************************************************************************/
325 void ringbuffer_test_reading_and_writing( void )
326 {
327   unsigned int
328     loop,
329     subloop,
330     cpu_count;
331
332   thread_state_t
333     *thread_handles;
334
335   struct lfds600_ringbuffer_state
336     *rs;
337
338   struct ringbuffer_test_reading_and_writing_state
339     *rtrws;
340
341   struct lfds600_validation_info
342     vi = { 0, 0 };
343
344   enum data_structure_validity
345     dvs[3];
346
347   /* TRD : we create a single ringbuffer
348            with 100000 elements
349            the ringbuffers starts empty
350
351            we create one thread per CPU
352            where each thread busy-works writing
353            and then immediately reading
354            for ten seconds
355
356            the user data in each written element is a combination
357            of the thread number and the counter
358
359            while a thread runs, it keeps track of the
360            counters for the other threads and throws an error
361            if it sees the number stay the same or decrease
362   */
363
364   internal_display_test_name( "Reading and writing (10 seconds)" );
365
366   cpu_count = abstraction_cpu_count();
367
368   lfds600_ringbuffer_new( &rs, 100000, NULL, NULL );
369
370   rtrws = malloc( sizeof(struct ringbuffer_test_reading_and_writing_state) * cpu_count );
371
372   for( loop = 0 ; loop < cpu_count ; loop++ )
373   {
374     (rtrws+loop)->rs = rs;
375     (rtrws+loop)->counter = (lfds600_atom_t) loop << (sizeof(lfds600_atom_t)*8-8);
376     (rtrws+loop)->cpu_count = cpu_count;
377     (rtrws+loop)->error_flag = LOWERED;
378     (rtrws+loop)->per_thread_counters = malloc( sizeof(lfds600_atom_t) * cpu_count );
379
380     for( subloop = 0 ; subloop < cpu_count ; subloop++ )
381       *((rtrws+loop)->per_thread_counters+subloop) = 0;
382   }
383
384   thread_handles = malloc( sizeof(thread_state_t) * cpu_count );
385
386   for( loop = 0 ; loop < cpu_count ; loop++ )
387     abstraction_thread_start( &thread_handles[loop], loop, ringbuffer_test_thread_reader_writer, rtrws+loop );
388
389   for( loop = 0 ; loop < cpu_count ; loop++ )
390     abstraction_thread_wait( thread_handles[loop] );
391
392   free( thread_handles );
393
394   lfds600_ringbuffer_query( rs, LFDS600_RINGBUFFER_QUERY_VALIDATE, (void *) &vi, (void *) dvs );
395
396   for( loop = 0 ; loop < cpu_count ; loop++ )
397     if( (rtrws+loop)->error_flag == RAISED )
398       dvs[0] = VALIDITY_INVALID_TEST_DATA;
399
400   for( loop = 0 ; loop < cpu_count ; loop++ )
401     free( (rtrws+loop)->per_thread_counters );
402
403   free( rtrws );
404
405   lfds600_ringbuffer_delete( rs, NULL, NULL );
406
407   internal_display_test_result( 3, "queue", dvs[0], "queue freelist", dvs[1], "freelist", dvs[2] );
408
409   return;
410 }
411
412
413
414
415
416 /****************************************************************************/
417 thread_return_t CALLING_CONVENTION ringbuffer_test_thread_reader_writer( void *ringbuffer_test_reading_and_writing_state )
418 {
419   struct ringbuffer_test_reading_and_writing_state
420     *rtrws;
421
422   struct lfds600_freelist_element
423     *fe;
424
425   lfds600_atom_t
426     user_data,
427     thread,
428     count;
429
430   time_t
431     start_time;
432
433   assert( ringbuffer_test_reading_and_writing_state != NULL );
434
435   rtrws = (struct ringbuffer_test_reading_and_writing_state *) ringbuffer_test_reading_and_writing_state;
436
437   time( &start_time );
438
439   while( time(NULL) < start_time + 10 )
440   {
441     lfds600_ringbuffer_get_write_element( rtrws->rs, &fe, NULL );
442     lfds600_freelist_set_user_data_in_element( fe, (void *) (lfds600_atom_t) (rtrws->counter++) );
443     lfds600_ringbuffer_put_write_element( rtrws->rs, fe );
444
445     lfds600_ringbuffer_get_read_element( rtrws->rs, &fe );
446     lfds600_freelist_get_user_data_from_element( fe, (void *) &user_data );
447
448     thread = user_data >> (sizeof(lfds600_atom_t)*8-8);
449     count = (user_data << 8) >> 8;
450
451     if( thread >= rtrws->cpu_count )
452       rtrws->error_flag = RAISED;
453     else
454     {
455       if( count < rtrws->per_thread_counters[thread] )
456         rtrws->error_flag = RAISED;
457
458       if( count >= rtrws->per_thread_counters[thread] )
459         rtrws->per_thread_counters[thread] = count+1;
460     }
461
462     lfds600_ringbuffer_put_read_element( rtrws->rs, fe );
463   }
464
465   return( (thread_return_t) EXIT_SUCCESS );
466 }
467