2 #include "libtest_tests_internal.h"
5 struct test_per_thread_state
10 struct lfds710_queue_bss_state
14 /***** private prototypes *****/
15 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_enqueuer( void *libtest_threadset_per_thread_state );
16 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_dequeuer( void *libtest_threadset_per_thread_state );
22 /****************************************************************************/
23 void libtest_tests_queue_bss_enqueuing_and_dequeuing( struct lfds710_list_asu_state *list_of_logical_processors, struct libshared_memory_state *ms, enum lfds710_misc_validity *dvs )
27 number_logical_processors;
29 struct lfds710_list_asu_element
32 struct lfds710_queue_bss_element
35 struct lfds710_queue_bss_state
38 struct libtest_logical_processor
42 struct libtest_threadset_per_thread_state
45 struct libtest_threadset_state
48 struct test_per_thread_state
51 LFDS710_PAL_ASSERT( list_of_logical_processors != NULL );
52 LFDS710_PAL_ASSERT( ms != NULL );
53 LFDS710_PAL_ASSERT( dvs != NULL );
55 /* TRD : so, this is the real test
56 problem is, because we use memory barriers only
57 and we only support one producer and one consumer
58 we need to ensure these threads are on different physical cores
59 if they're on the same core, the code would work even without memory barriers
61 problem is, in the test application, we only know the *number* of logical cores
62 obtaining topology information adds a great deal of complexity to the test app
63 and makes porting much harder
65 so, we know how many logical cores there are; my thought is to partially
66 permutate over them - we always run the producer on core 0, but we iterate
67 over the other logical cores, running the test once each time, with the
68 consumer being run on core 0, then core 1, then core 2, etc
70 (we run on core 0 for the single-cpu case; it's redundent, since a single
71 logical core running both producer and consumer will work, but otherwise
72 we have to skip the test, which is confusing for the user)
74 the test is one thread enqueuing and one thread dequeuing for two seconds
77 *dvs = LFDS710_MISC_VALIDITY_VALID;
80 lfds710_list_asu_query( list_of_logical_processors, LFDS710_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
82 tpts = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct test_per_thread_state) * 2, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
83 pts = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct libtest_threadset_per_thread_state) * 2, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
85 for( loop = 0 ; loop < 2 ; loop++ )
87 (tpts+loop)->qs = &qs;
88 (tpts+loop)->error_flag = LOWERED;
91 /* TRD : producer always on core 0
92 iterate over the other cores with consumer
95 lasue = LFDS710_LIST_ASU_GET_START( *list_of_logical_processors );
96 lp_first = LFDS710_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
98 while( lasue != NULL )
100 lp = LFDS710_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
102 lfds710_queue_bss_init_valid_on_current_logical_core( &qs, element_array, 4, NULL );
104 libtest_threadset_init( &ts, NULL );
106 LFDS710_MISC_BARRIER_STORE;
107 lfds710_misc_force_store();
109 libtest_threadset_add_thread( &ts, &pts[0], lp_first, thread_enqueuer, &tpts[0] );
110 libtest_threadset_add_thread( &ts, &pts[1], lp, thread_dequeuer, &tpts[1] );
112 libtest_threadset_run( &ts );
113 libtest_threadset_cleanup( &ts );
115 LFDS710_MISC_BARRIER_LOAD;
117 lfds710_queue_bss_cleanup( &qs, NULL );
119 lasue = LFDS710_LIST_ASU_GET_NEXT( *lasue );
122 if( (tpts+1)->error_flag == RAISED )
123 *dvs = LFDS710_MISC_VALIDITY_INVALID_TEST_DATA;
132 /****************************************************************************/
133 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_enqueuer( void *libtest_threadset_per_thread_state )
142 struct libtest_threadset_per_thread_state
145 struct test_per_thread_state
152 LFDS710_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
154 LFDS710_PAL_ASSERT( libtest_threadset_per_thread_state != NULL );
156 pts = (struct libtest_threadset_per_thread_state *) libtest_threadset_per_thread_state;
157 tpts = LIBTEST_THREADSET_GET_USER_STATE_FROM_PER_THREAD_STATE( *pts );
159 libtest_threadset_thread_ready_and_wait( pts );
161 current_time = start_time = time( NULL );
163 while( current_time < start_time + 2 )
165 rv = lfds710_queue_bss_enqueue( tpts->qs, NULL, (void *) datum );
171 if( time_loop++ == TIME_LOOP_COUNT )
174 time( ¤t_time );
178 LFDS710_MISC_BARRIER_STORE;
180 lfds710_misc_force_store();
182 return LIBSHARED_PAL_THREAD_RETURN_CAST(RETURN_SUCCESS);
189 /****************************************************************************/
190 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_dequeuer( void *libtest_threadset_per_thread_state )
200 struct libtest_threadset_per_thread_state
203 struct test_per_thread_state
210 LFDS710_MISC_BARRIER_LOAD;
212 LFDS710_PAL_ASSERT( libtest_threadset_per_thread_state != NULL );
214 pts = (struct libtest_threadset_per_thread_state *) libtest_threadset_per_thread_state;
215 tpts = LIBTEST_THREADSET_GET_USER_STATE_FROM_PER_THREAD_STATE( *pts );
217 libtest_threadset_thread_ready_and_wait( pts );
219 current_time = start_time = time( NULL );
221 while( current_time < start_time + 2 )
223 rv = lfds710_queue_bss_dequeue( tpts->qs, NULL, (void *) &datum );
227 if( datum != expected_datum )
228 tpts->error_flag = RAISED;
230 if( ++expected_datum == 4 )
234 if( time_loop++ == TIME_LOOP_COUNT )
237 time( ¤t_time );
241 LFDS710_MISC_BARRIER_STORE;
243 lfds710_misc_force_store();
245 return LIBSHARED_PAL_THREAD_RETURN_CAST(RETURN_SUCCESS);