]> pd.if.org Git - liblfds/blob - liblfds/liblfds7.0.0/test/src/test_lfds700_queue_dequeuing.c
Initial import (all versions, including the new 7.1.0)
[liblfds] / liblfds / liblfds7.0.0 / test / src / test_lfds700_queue_dequeuing.c
1 /***** includes *****/
2 #include "internal.h"
3
4 /***** structs *****/
5 struct test_state
6 {
7   enum flag
8     error_flag;
9
10   struct lfds700_queue_state
11     *qs;
12 };
13
14 struct test_element
15 {
16   struct lfds700_queue_element
17     qe;
18 };
19
20 /***** private prototypes *****/
21 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_simple_dequeuer( void *util_thread_starter_thread_state );
22
23
24
25
26
27 /****************************************************************************/
28 void test_lfds700_queue_dequeuing( struct lfds700_list_asu_state *list_of_logical_processors, lfds700_pal_uint_t memory_in_megabytes )
29 {
30   enum lfds700_misc_validity
31     dvs = LFDS700_MISC_VALIDITY_VALID;
32
33   lfds700_pal_uint_t
34     loop,
35     number_elements_with_dummy_element,
36     number_elements_without_dummy_element,
37     number_logical_processors;
38
39   struct lfds700_list_asu_element
40     *lasue;
41
42   struct lfds700_misc_prng_state
43     ps;
44
45   struct lfds700_queue_state
46     qs;
47
48   struct lfds700_misc_validation_info
49     vi = { 0, 0 };
50
51   struct test_pal_logical_processor
52     *lp;
53
54   struct util_thread_starter_state
55     *tts;
56
57   struct test_element
58     *te_array;
59
60   struct test_state
61     *ts;
62
63   test_pal_thread_state_t
64     *thread_handles;
65
66   assert( list_of_logical_processors != NULL );
67   // TRD : memory_in_megabytes can be any value in its range
68
69   /* TRD : create a queue, add 1,000,000 elements
70
71            use a single thread to enqueue every element
72            each elements user data is an incrementing counter
73
74            then run one thread per CPU
75            where each busy-works dequeuing
76
77            when an element is dequeued, we check (on a per-thread basis) the
78            value dequeued is greater than the element previously dequeued
79
80            note we have no variation in the test for CAS+GC vs DWCAS
81            this is because all we do is dequeue
82            what we actually want to stress test is the queue
83            not CAS
84            so it's better to let the dequeue run as fast as possible
85   */
86
87   internal_display_test_name( "Dequeuing" );
88
89   lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
90
91   lfds700_misc_prng_init( &ps );
92
93   number_elements_with_dummy_element = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / sizeof(struct test_element);
94   number_elements_without_dummy_element = number_elements_with_dummy_element - 1;
95
96   te_array = util_aligned_malloc( sizeof(struct test_element) * number_elements_with_dummy_element, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
97
98   lfds700_queue_init_valid_on_current_logical_core( &qs, &(te_array + number_elements_without_dummy_element)->qe, &ps, NULL );
99
100   for( loop = 0 ; loop < number_elements_without_dummy_element ; loop++ )
101   {
102     LFDS700_QUEUE_SET_VALUE_IN_ELEMENT( (te_array+loop)->qe, loop );
103     lfds700_queue_enqueue( &qs, &(te_array+loop)->qe, &ps );
104   }
105
106   ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
107
108   for( loop = 0 ; loop < number_logical_processors ; loop++ )
109   {
110     (ts+loop)->qs = &qs;
111     (ts+loop)->error_flag = LOWERED;
112   }
113
114   thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
115
116   util_thread_starter_new( &tts, number_logical_processors );
117
118   LFDS700_MISC_BARRIER_STORE;
119
120   lfds700_misc_force_store();
121
122   loop = 0;
123   lasue = NULL;
124
125   while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
126   {
127     lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
128     util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_simple_dequeuer, ts+loop );
129     loop++;
130   }
131
132   util_thread_starter_run( tts );
133
134   for( loop = 0 ; loop < number_logical_processors ; loop++ )
135     test_pal_thread_wait( thread_handles[loop] );
136
137   util_thread_starter_delete( tts );
138
139   free( thread_handles );
140
141   LFDS700_MISC_BARRIER_LOAD;
142
143   // TRD : check queue is empty
144   lfds700_queue_query( &qs, LFDS700_QUEUE_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
145
146   // TRD : check for raised error flags
147   for( loop = 0 ; loop < number_logical_processors ; loop++ )
148     if( (ts+loop)->error_flag == RAISED )
149       dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
150
151   free( ts );
152
153   util_aligned_free( te_array );
154
155   lfds700_queue_cleanup( &qs, NULL );
156
157   internal_display_test_result( 1, "queue", dvs );
158
159   return;
160 }
161
162
163
164
165
166 /****************************************************************************/
167 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_simple_dequeuer( void *util_thread_starter_thread_state )
168 {
169   lfds700_pal_uint_t
170     *prev_value,
171     *value;
172
173   struct lfds700_misc_prng_state
174     ps;
175
176   struct lfds700_queue_element
177     *qe;
178
179   struct test_state
180     *ts;
181
182   struct util_thread_starter_thread_state
183     *tsts;
184
185   LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
186
187   assert( util_thread_starter_thread_state != NULL );
188
189   tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
190   ts = (struct test_state *) tsts->thread_user_state;
191
192   lfds700_misc_prng_init( &ps );
193
194   lfds700_queue_dequeue( ts->qs, &qe, &ps );
195   prev_value = LFDS700_QUEUE_GET_VALUE_FROM_ELEMENT( *qe );
196
197   util_thread_starter_ready_and_wait( tsts );
198
199   while( lfds700_queue_dequeue(ts->qs, &qe, &ps) )
200   {
201     value = LFDS700_QUEUE_GET_VALUE_FROM_ELEMENT( *qe );
202
203     if( value <= prev_value )
204       ts->error_flag = RAISED;
205
206     prev_value = value;
207   }
208
209   LFDS700_MISC_BARRIER_STORE;
210
211   lfds700_misc_force_store();
212
213   return( (test_pal_thread_return_t) EXIT_SUCCESS );
214 }
215