]> pd.if.org Git - liblfds/blob - liblfds/liblfds7.0.0/test/src/test_lfds700_ringbuffer_reading.c
Initial import (all versions, including the new 7.1.0)
[liblfds] / liblfds / liblfds7.0.0 / test / src / test_lfds700_ringbuffer_reading.c
1 /***** includes *****/
2 #include "internal.h"
3
4 /***** structs *****/
5 struct test_state
6 {
7   enum flag
8     error_flag;
9
10   lfds700_pal_uint_t
11     read_count;
12
13   struct lfds700_ringbuffer_state
14     *rs;
15 };
16
17 /***** private prototypes *****/
18 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_simple_reader( void *util_thread_starter_thread_state );
19
20
21
22
23
24 /****************************************************************************/
25 void test_lfds700_ringbuffer_reading( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
26 {
27   enum lfds700_misc_validity
28     dvs[2] = { LFDS700_MISC_VALIDITY_VALID, LFDS700_MISC_VALIDITY_VALID };
29
30   lfds700_pal_uint_t
31     loop,
32     number_elements_with_dummy_element,
33     number_elements_without_dummy_element,
34     number_logical_processors,
35     total_read = 0;
36
37   struct lfds700_list_asu_element
38     *lasue;
39
40   struct lfds700_misc_prng_state
41     ps;
42
43   struct lfds700_ringbuffer_element
44     *re_array;
45
46   struct lfds700_ringbuffer_state
47     rs;
48
49   struct lfds700_misc_validation_info
50     vi;
51
52   struct test_pal_logical_processor
53     *lp;
54
55   struct util_thread_starter_state
56     *tts;
57
58   struct test_state
59     *ts;
60
61   test_pal_thread_state_t
62     *thread_handles;
63
64   assert( list_of_logical_processors != NULL );
65   // TRD : memory_in_megabytes can be any value in its range
66
67   /* TRD : we create a single ringbuffer
68            with 1,000,000 elements
69            we populate the ringbuffer, where the
70            user data is an incrementing counter
71
72            we create one thread per CPU
73            where each thread busy-works,
74            reading until the ringbuffer is empty
75
76            each thread keep track of the number of reads it manages
77            and that each user data it reads is greater than the
78            previous user data that was read
79   */
80
81   internal_display_test_name( "Reading" );
82
83   lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
84
85   lfds700_misc_prng_init( &ps );
86
87   number_elements_with_dummy_element = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / sizeof(struct lfds700_ringbuffer_element);
88   number_elements_without_dummy_element = number_elements_with_dummy_element - 1;
89
90   vi.min_elements = 0;
91   vi.max_elements = number_elements_without_dummy_element;
92
93   re_array = util_aligned_malloc( sizeof(struct lfds700_ringbuffer_element) * number_elements_with_dummy_element, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
94
95   lfds700_ringbuffer_init_valid_on_current_logical_core( &rs, re_array, number_elements_with_dummy_element, &ps, NULL );
96
97   // TRD : init the ringbuffer contents for the test
98   for( loop = 0 ; loop < number_elements_without_dummy_element ; loop++ )
99     lfds700_ringbuffer_write( &rs, NULL, (void *) (size_t) loop, NULL, NULL, NULL, &ps );
100
101   ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
102
103   for( loop = 0 ; loop < number_logical_processors ; loop++ )
104   {
105     (ts+loop)->rs = &rs;
106     (ts+loop)->read_count = 0;
107     (ts+loop)->error_flag = LOWERED;
108   }
109
110   thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
111
112   util_thread_starter_new( &tts, number_logical_processors );
113
114   LFDS700_MISC_BARRIER_STORE;
115
116   lfds700_misc_force_store();
117
118   loop = 0;
119   lasue = NULL;
120
121   while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
122   {
123     lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
124     util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_simple_reader, ts+loop );
125     loop++;
126   }
127
128   util_thread_starter_run( tts );
129
130   for( loop = 0 ; loop < number_logical_processors ; loop++ )
131     test_pal_thread_wait( thread_handles[loop] );
132
133   util_thread_starter_delete( tts );
134
135   free( thread_handles );
136
137   LFDS700_MISC_BARRIER_LOAD;
138
139   lfds700_ringbuffer_query( &rs, LFDS700_RINGBUFFER_QUERY_SINGLETHREADED_VALIDATE, (void *) &vi, (void *) dvs );
140
141   // TRD : check for raised error flags
142   for( loop = 0 ; loop < number_logical_processors ; loop++ )
143     if( (ts+loop)->error_flag == RAISED )
144       dvs[0] = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
145
146   // TRD : check thread reads total to 1,000,000
147   for( loop = 0 ; loop < number_logical_processors ; loop++ )
148     total_read += (ts+loop)->read_count;
149
150   if( total_read < number_elements_without_dummy_element )
151     dvs[0] = LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS;
152
153   if( total_read > number_elements_without_dummy_element )
154     dvs[0] = LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
155
156   free( ts );
157
158   lfds700_ringbuffer_cleanup( &rs, NULL );
159
160   util_aligned_free( re_array );
161
162   internal_display_test_result( 2, "queue", dvs[0], "freelist", dvs[1] );
163
164   return;
165 }
166
167
168
169
170
171 /****************************************************************************/
172 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_simple_reader( void *util_thread_starter_thread_state )
173 {
174   lfds700_pal_uint_t
175     *prev_value,
176     *value;
177
178   struct lfds700_misc_prng_state
179     ps;
180
181   struct test_state
182     *ts;
183
184   struct util_thread_starter_thread_state
185     *tsts;
186
187   LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
188
189   assert( util_thread_starter_thread_state != NULL );
190
191   tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
192   ts = (struct test_state *) tsts->thread_user_state;
193
194   lfds700_misc_prng_init( &ps );
195
196   lfds700_ringbuffer_read( ts->rs, NULL, (void **) &prev_value, &ps );
197   ts->read_count++;
198
199   util_thread_starter_ready_and_wait( tsts );
200
201   while( lfds700_ringbuffer_read(ts->rs, NULL, (void **) &value, &ps) )
202   {
203     if( value <= prev_value )
204       ts->error_flag = RAISED;
205
206     prev_value = value;
207
208     ts->read_count++;
209   }
210
211   LFDS700_MISC_BARRIER_STORE;
212
213   lfds700_misc_force_store();
214
215   return( (test_pal_thread_return_t) EXIT_SUCCESS );
216 }
217