]> pd.if.org Git - liblfds/blob - liblfds/liblfds7.0.0/test/src/test_lfds700_stack_rapid_popping_and_pushing.c
Initial import (all versions, including the new 7.1.0)
[liblfds] / liblfds / liblfds7.0.0 / test / src / test_lfds700_stack_rapid_popping_and_pushing.c
1 /***** includes *****/
2 #include "internal.h"
3
4 /***** structs *****/
5 struct test_state
6 {
7   struct lfds700_stack_state
8     *ss;
9 };
10
11 struct test_element
12 {
13   struct lfds700_stack_element
14     se;
15
16   lfds700_pal_uint_t
17     datum;
18 };
19
20 /***** private prototypes *****/
21 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_rapid_popping_and_pushing( void *util_thread_starter_thread_state );
22
23
24
25
26
27 /****************************************************************************/
28 void test_lfds700_stack_rapid_popping_and_pushing( struct lfds700_list_asu_state *list_of_logical_processors )
29 {
30   enum lfds700_misc_validity
31     dvs = LFDS700_MISC_VALIDITY_VALID;
32
33   lfds700_pal_uint_t
34     loop,
35     number_logical_processors;
36
37   struct lfds700_misc_prng_state
38     ps;
39
40   struct lfds700_list_asu_element
41     *lasue;
42
43   struct lfds700_stack_state
44     ss;
45
46   struct lfds700_misc_validation_info
47     vi = { 0, 0 };
48
49   struct test_pal_logical_processor
50     *lp;
51
52   struct util_thread_starter_state
53     *tts;
54
55   struct test_element
56     *te_array;
57
58   struct test_state
59     *ts;
60
61   test_pal_thread_state_t
62     *thread_handles;
63
64   assert( list_of_logical_processors != NULL );
65   // TRD : st can be any value in its range
66
67   /* TRD : in these tests there is a fundamental antagonism between
68            how much checking/memory clean up that we do and the
69            likelyhood of collisions between threads in their lock-free
70            operations
71
72            the lock-free operations are very quick; if we do anything
73            much at all between operations, we greatly reduce the chance
74            of threads colliding
75
76            so we have some tests which do enough checking/clean up that
77            they can tell the stack is valid and don't leak memory
78            and here, this test now is one of those which does minimal
79            checking - in fact, the nature of the test is that you can't
80            do any real checking - but goes very quickly
81
82            what we do is create a small stack and then run one thread
83            per CPU, where each thread simply pushes and then immediately
84            pops
85
86            the test runs for ten seconds
87
88            after the test is done, the only check we do is to traverse
89            the stack, checking for loops and ensuring the number of
90            elements is correct
91   */
92
93   internal_display_test_name( "Rapid popping and pushing (%d seconds)", TEST_DURATION_IN_SECONDS );
94
95   lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
96
97   lfds700_misc_prng_init( &ps );
98
99   ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
100
101   lfds700_stack_init_valid_on_current_logical_core( &ss, NULL );
102
103   for( loop = 0 ; loop < number_logical_processors ; loop++ )
104     (ts+loop)->ss = &ss;
105
106   thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
107
108   // TRD : we need one element per thread
109   te_array = util_aligned_malloc( sizeof(struct test_element) * number_logical_processors, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
110
111   for( loop = 0 ; loop < number_logical_processors ; loop++ )
112   {
113     LFDS700_STACK_SET_VALUE_IN_ELEMENT( (te_array+loop)->se, te_array+loop );
114     lfds700_stack_push( &ss, &(te_array+loop)->se, &ps );
115   }
116
117   util_thread_starter_new( &tts, number_logical_processors );
118
119   LFDS700_MISC_BARRIER_STORE;
120
121   lfds700_misc_force_store();
122
123   loop = 0;
124   lasue = NULL;
125
126   while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
127   {
128     lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
129     util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_rapid_popping_and_pushing, ts+loop );
130     loop++;
131   }
132
133   util_thread_starter_run( tts );
134
135   for( loop = 0 ; loop < number_logical_processors ; loop++ )
136     test_pal_thread_wait( thread_handles[loop] );
137
138   util_thread_starter_delete( tts );
139
140   free( thread_handles );
141
142   LFDS700_MISC_BARRIER_LOAD;
143
144   vi.min_elements = vi.max_elements = number_logical_processors;
145
146   lfds700_stack_query( &ss, LFDS700_STACK_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
147
148   lfds700_stack_cleanup( &ss, NULL );
149
150   util_aligned_free( te_array );
151
152   free( ts );
153
154   // TRD : print the test result
155   internal_display_test_result( 1, "stack", dvs );
156
157   return;
158 }
159
160
161
162
163
164 /****************************************************************************/
165 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_rapid_popping_and_pushing( void *util_thread_starter_thread_state )
166 {
167   lfds700_pal_uint_t
168     time_loop = 0;
169
170   struct lfds700_misc_prng_state
171     ps;
172
173   struct lfds700_stack_element
174     *se;
175
176   struct test_state
177     *ts;
178
179   struct util_thread_starter_thread_state
180     *tsts;
181
182   time_t
183     current_time,
184     start_time;
185
186   LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
187
188   assert( util_thread_starter_thread_state != NULL );
189
190   tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
191   ts = (struct test_state *) tsts->thread_user_state;
192
193   lfds700_misc_prng_init( &ps );
194
195   util_thread_starter_ready_and_wait( tsts );
196
197   current_time = start_time = time( NULL );
198
199   while( current_time < start_time + TEST_DURATION_IN_SECONDS )
200   {
201     lfds700_stack_pop( ts->ss, &se, &ps );
202     lfds700_stack_push( ts->ss, se, &ps );
203
204     if( time_loop++ == TIME_LOOP_COUNT )
205     {
206       time_loop = 0;
207       time( &current_time );
208     }
209   }
210
211   LFDS700_MISC_BARRIER_STORE;
212
213   lfds700_misc_force_store();
214
215   return( (test_pal_thread_return_t) EXIT_SUCCESS );
216 }
217