]> pd.if.org Git - liblfds/blob - liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_ringbuffer_writing.c
Initial import (all versions, including the new 7.1.0)
[liblfds] / liblfds / liblfds7.1.0 / test_and_benchmark / libtest / src / libtest_tests / libtest_tests_ringbuffer_writing.c
1 /***** includes *****/
2 #include "libtest_tests_internal.h"
3
4 /***** structs *****/
5 struct test_element
6 {
7   lfds710_pal_uint_t
8     thread_number,
9     datum;
10 };
11
12 struct test_per_thread_state
13 {
14   lfds710_pal_uint_t
15     thread_number,
16     write_count;
17
18   struct test_element
19     te;
20
21   struct lfds710_ringbuffer_state
22     *rs;
23 };
24
25 /***** private prototypes *****/
26 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_simple_writer( void *libtest_threadset_per_thread_state );
27
28
29
30
31
32 /****************************************************************************/
33 void libtest_tests_ringbuffer_writing( struct lfds710_list_asu_state *list_of_logical_processors, struct libshared_memory_state *ms, enum lfds710_misc_validity *dvs )
34 {
35   enum lfds710_misc_validity
36     local_dvs[2] = { LFDS710_MISC_VALIDITY_VALID, LFDS710_MISC_VALIDITY_VALID };
37
38   lfds710_pal_uint_t
39     loop,
40     number_elements,
41     number_logical_processors,
42     *per_thread_counters;
43
44   struct lfds710_list_asu_element
45     *lasue = NULL;
46
47   struct lfds710_ringbuffer_element
48     *re_array;
49
50   struct lfds710_ringbuffer_state
51     rs;
52
53   struct lfds710_misc_validation_info
54     vi;
55
56   struct libtest_logical_processor
57     *lp;
58
59   struct libtest_threadset_per_thread_state
60     *pts;
61
62   struct libtest_threadset_state
63     ts;
64
65   struct test_element
66     *te,
67     *te_array;
68
69   struct test_per_thread_state
70     *tpts;
71
72   LFDS710_PAL_ASSERT( list_of_logical_processors != NULL );
73   LFDS710_PAL_ASSERT( ms != NULL );
74   LFDS710_PAL_ASSERT( dvs != NULL );
75
76   /* TRD : we create a single ringbuffer
77            with n elements
78            we create n test elements
79            which are thread_number/counter pairs
80            init them to safe values
81            and fully populate the ringbuffer
82
83            we create one thread per CPU
84            where each thread busy-works writing
85            for ten seconds; each thread has one extra element
86            which it uses for the first write and after that
87            it uses the element it picks up from overwriting
88
89            the user data in each written element is a combination
90            of the thread number and the counter
91
92            after the threads are complete, we validate by
93            checking the user data counters increment on a per thread
94            basis
95   */
96
97   *dvs = LFDS710_MISC_VALIDITY_VALID;
98
99   lfds710_list_asu_query( list_of_logical_processors, LFDS710_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
100
101   // TRD : allocate
102   tpts = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct test_per_thread_state) * number_logical_processors, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
103   pts = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct libtest_threadset_per_thread_state) * number_logical_processors, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
104   per_thread_counters = libshared_memory_alloc_from_unknown_node( ms, sizeof(lfds710_pal_uint_t) * number_logical_processors, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
105   re_array = libshared_memory_alloc_largest_possible_array_from_unknown_node( ms, sizeof(struct test_element) + sizeof(struct lfds710_ringbuffer_element), LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES, &number_elements );
106   te_array = (struct test_element *) ( re_array + number_elements );
107
108   vi.min_elements = number_elements;
109   vi.max_elements = number_elements;
110
111   lfds710_ringbuffer_init_valid_on_current_logical_core( &rs, re_array, number_elements, NULL );
112
113   // TRD : init the test elements and write them into the ringbuffer
114   for( loop = 1 ; loop < number_elements ; loop++ )
115   {
116     te_array[loop].thread_number = 0;
117     te_array[loop].datum = 0;
118     lfds710_ringbuffer_write( &rs, NULL, &te_array[loop], NULL, NULL, NULL );
119   }
120
121   libtest_threadset_init( &ts, NULL );
122
123   loop = 0;
124
125   while( LFDS710_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors,lasue) )
126   {
127     lp = LFDS710_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
128     (tpts+loop)->rs = &rs;
129     (tpts+loop)->thread_number = loop;
130     (tpts+loop)->write_count = 0;
131
132     libtest_threadset_add_thread( &ts, &pts[loop], lp, thread_simple_writer, &tpts[loop] );
133
134     loop++;
135   }
136
137   // TRD : run the test
138   libtest_threadset_run( &ts );
139
140   libtest_threadset_cleanup( &ts );
141
142   // TRD : validate
143   LFDS710_MISC_BARRIER_LOAD;
144
145   // TRD : now check results
146   for( loop = 0 ; loop < number_logical_processors ; loop++ )
147     *(per_thread_counters+loop) = 0;
148
149   lfds710_ringbuffer_query( &rs, LFDS710_RINGBUFFER_QUERY_SINGLETHREADED_VALIDATE, &vi, (void *) local_dvs );
150
151   if( local_dvs[0] != LFDS710_MISC_VALIDITY_VALID )
152     *dvs = local_dvs[0];
153
154   if( local_dvs[1] != LFDS710_MISC_VALIDITY_VALID )
155     *dvs = local_dvs[1];
156
157   while( *dvs == LFDS710_MISC_VALIDITY_VALID and lfds710_ringbuffer_read(&rs, NULL, (void **) &te) )
158   {
159     if( te->thread_number >= number_logical_processors )
160     {
161       *dvs = LFDS710_MISC_VALIDITY_INVALID_TEST_DATA;
162       break;
163     }
164
165     if( per_thread_counters[te->thread_number] == 0 )
166       per_thread_counters[te->thread_number] = te->datum;
167
168     if( te->datum < per_thread_counters[te->thread_number] )
169       *dvs = LFDS710_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS;
170
171     if( te->datum >= per_thread_counters[te->thread_number] )
172       per_thread_counters[te->thread_number] = te->datum+1;
173   }
174
175   lfds710_ringbuffer_cleanup( &rs, NULL );
176
177   return;
178 }
179
180
181
182
183
184 /****************************************************************************/
185 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_simple_writer( void *libtest_threadset_per_thread_state )
186 {
187   enum lfds710_misc_flag
188     overwrite_occurred_flag;
189
190   lfds710_pal_uint_t
191     time_loop = 0;
192
193   struct libtest_threadset_per_thread_state
194     *pts;
195
196   struct test_element
197     *te;
198
199   struct test_per_thread_state
200     *tpts;
201
202   time_t
203     current_time,
204     start_time;
205
206   LFDS710_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
207
208   LFDS710_PAL_ASSERT( libtest_threadset_per_thread_state != NULL );
209
210   pts = (struct libtest_threadset_per_thread_state *) libtest_threadset_per_thread_state;
211   tpts = LIBTEST_THREADSET_GET_USER_STATE_FROM_PER_THREAD_STATE( *pts );
212
213   tpts->te.thread_number = 0;
214   tpts->te.datum = 0;
215
216   lfds710_ringbuffer_write( tpts->rs, NULL, &tpts->te, &overwrite_occurred_flag, NULL, (void **) &te );
217
218   libtest_threadset_thread_ready_and_wait( pts );
219
220   current_time = start_time = time( NULL );
221
222   while( current_time < start_time + TEST_DURATION_IN_SECONDS )
223   {
224     te->thread_number = tpts->thread_number;
225     te->datum = tpts->write_count++;
226
227     lfds710_ringbuffer_write( tpts->rs, NULL, te, &overwrite_occurred_flag, NULL, (void **) &te );
228
229     if( time_loop++ == TIME_LOOP_COUNT )
230     {
231       time_loop = 0;
232       time( &current_time );
233     }
234   }
235
236   LFDS710_MISC_BARRIER_STORE;
237
238   lfds710_misc_force_store();
239
240   return LIBSHARED_PAL_THREAD_RETURN_CAST(RETURN_SUCCESS);
241 }
242