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