]> pd.if.org Git - liblfds/blob - liblfds/liblfds7.0.0/test/src/test_lfds700_ringbuffer_reading_and_writing.c
Initial import (all versions, including the new 7.1.0)
[liblfds] / liblfds / liblfds7.0.0 / test / src / test_lfds700_ringbuffer_reading_and_writing.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     counter,
12     number_logical_processors,
13     *per_thread_counters,
14     thread_number;
15
16   struct lfds700_ringbuffer_state
17     *rs;
18 };
19
20 struct test_element
21 {
22   lfds700_pal_uint_t
23     datum,
24     thread_number;
25 };
26
27 /***** private prototypes *****/
28 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_reader_writer( void *util_thread_starter_thread_state );
29
30
31
32
33
34 /****************************************************************************/
35 void test_lfds700_ringbuffer_reading_and_writing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
36 {
37   enum lfds700_misc_validity
38     dvs[2] = { LFDS700_MISC_VALIDITY_VALID, LFDS700_MISC_VALIDITY_VALID };
39
40   lfds700_pal_uint_t
41     loop,
42     number_elements_with_dummy_element,
43     number_elements_without_dummy_element,
44     number_logical_processors,
45     subloop;
46
47   test_pal_thread_state_t
48     *thread_handles;
49
50   struct lfds700_list_asu_element
51     *lasue;
52
53   struct lfds700_misc_prng_state
54     ps;
55
56   struct lfds700_ringbuffer_element
57     *re_array;
58
59   struct lfds700_ringbuffer_state
60     rs;
61
62   struct lfds700_misc_validation_info
63     vi;
64
65   struct test_pal_logical_processor
66     *lp;
67
68   struct util_thread_starter_state
69     *tts;
70
71   struct test_element
72     *te_array;
73
74   struct test_state
75     *ts;
76
77   assert( list_of_logical_processors != NULL );
78   // TRD : memory_in_megabytes can be any value in its range
79
80   /* TRD : we create a single ringbuffer
81            with 100,000 elements
82            the ringbuffers starts empty
83
84            we create one thread per CPU
85            where each thread busy-works writing
86            and then immediately reading
87            for ten seconds
88
89            the user data in each written element is a combination
90            of the thread number and the counter
91
92            while a thread runs, it keeps track of the
93            counters for the other threads and throws an error
94            if it sees the number stay the same or decrease
95   */
96
97   internal_display_test_name( "Reading and writing (%d seconds)", TEST_DURATION_IN_SECONDS );
98
99   lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
100
101   lfds700_misc_prng_init( &ps );
102
103   number_elements_with_dummy_element = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / ( sizeof(struct test_element) + sizeof(struct lfds700_ringbuffer_element) );
104   number_elements_without_dummy_element = number_elements_with_dummy_element - 1;
105
106   vi.min_elements = 0;
107   vi.max_elements = number_elements_without_dummy_element;
108
109   re_array = util_aligned_malloc( sizeof(struct lfds700_ringbuffer_element) * number_elements_with_dummy_element, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
110
111   lfds700_ringbuffer_init_valid_on_current_logical_core( &rs, re_array, number_elements_with_dummy_element, &ps, NULL );
112
113   te_array = util_malloc_wrapper( sizeof(struct test_element) * number_elements_without_dummy_element );
114
115   // TRD : populate the ringbuffer
116   for( loop = 0 ; loop < number_elements_without_dummy_element ; loop++ )
117   {
118     te_array[loop].thread_number = 0;
119     te_array[loop].datum = (lfds700_pal_uint_t) -1 ;
120     lfds700_ringbuffer_write( &rs, NULL, &te_array[loop], NULL, NULL, NULL, &ps );
121   }
122
123   ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
124
125   for( loop = 0 ; loop < number_logical_processors ; loop++ )
126   {
127     (ts+loop)->rs = &rs;
128     (ts+loop)->thread_number = loop;
129     (ts+loop)->counter = 0;
130     (ts+loop)->number_logical_processors = number_logical_processors;
131     (ts+loop)->error_flag = LOWERED;
132     (ts+loop)->per_thread_counters = util_malloc_wrapper( sizeof(lfds700_pal_uint_t) * number_logical_processors );
133
134     for( subloop = 0 ; subloop < number_logical_processors ; subloop++ )
135       *((ts+loop)->per_thread_counters+subloop) = 0;
136   }
137
138   thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
139
140   util_thread_starter_new( &tts, number_logical_processors );
141
142   LFDS700_MISC_BARRIER_STORE;
143
144   lfds700_misc_force_store();
145
146   loop = 0;
147   lasue = NULL;
148
149   while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
150   {
151     lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
152     util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_reader_writer, ts+loop );
153     loop++;
154   }
155
156   util_thread_starter_run( tts );
157
158   for( loop = 0 ; loop < number_logical_processors ; loop++ )
159     test_pal_thread_wait( thread_handles[loop] );
160
161   util_thread_starter_delete( tts );
162
163   free( thread_handles );
164
165   LFDS700_MISC_BARRIER_LOAD;
166
167   lfds700_ringbuffer_query( &rs, LFDS700_RINGBUFFER_QUERY_SINGLETHREADED_VALIDATE, (void *) &vi, (void *) dvs );
168
169   for( loop = 0 ; loop < number_logical_processors ; loop++ )
170     if( (ts+loop)->error_flag == RAISED )
171       dvs[0] = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
172
173   for( loop = 0 ; loop < number_logical_processors ; loop++ )
174     free( (ts+loop)->per_thread_counters );
175
176   free( ts );
177
178   lfds700_ringbuffer_cleanup( &rs, NULL );
179
180   util_aligned_free( re_array );
181
182   free( te_array );
183
184   internal_display_test_result( 2, "queue", dvs[0], "freelist", dvs[1] );
185
186   return;
187 }
188
189
190
191
192
193 /****************************************************************************/
194 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_reader_writer( void *util_thread_starter_thread_state )
195 {
196   lfds700_pal_uint_t
197     time_loop = 0;
198
199   struct lfds700_misc_prng_state
200     ps;
201
202   struct test_element
203     *te;
204
205   struct test_state
206     *ts;
207
208   struct util_thread_starter_thread_state
209     *tsts;
210
211   time_t
212     current_time,
213     start_time;
214
215   LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
216
217   assert( util_thread_starter_thread_state != NULL );
218
219   tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
220   ts = (struct test_state *) tsts->thread_user_state;
221
222   lfds700_misc_prng_init( &ps );
223
224   util_thread_starter_ready_and_wait( tsts );
225
226   current_time = start_time = time( NULL );
227
228   while( current_time < start_time + TEST_DURATION_IN_SECONDS )
229   {
230     lfds700_ringbuffer_read( ts->rs, NULL, (void **) &te, &ps );
231
232     if( te->thread_number >= ts->number_logical_processors )
233       ts->error_flag = RAISED;
234     else
235     {
236       if( te->datum < ts->per_thread_counters[te->thread_number] )
237         ts->error_flag = RAISED;
238
239       if( te->datum >= ts->per_thread_counters[te->thread_number] )
240         ts->per_thread_counters[te->thread_number] = te->datum+1;
241     }
242
243     te->thread_number = ts->thread_number;
244     te->datum = ts->counter++;
245
246     lfds700_ringbuffer_write( ts->rs, NULL, te, NULL, NULL, NULL, &ps );
247
248     if( time_loop++ == TIME_LOOP_COUNT )
249     {
250       time_loop = 0;
251       time( &current_time );
252     }
253   }
254
255   LFDS700_MISC_BARRIER_STORE;
256
257   lfds700_misc_force_store();
258
259   return( (test_pal_thread_return_t) EXIT_SUCCESS );
260 }
261