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