]> pd.if.org Git - liblfds/blob - liblfds/liblfds7.0.0/test/src/test_lfds700_freelist_rapid_popping_and_pushing.c
Initial import (all versions, including the new 7.1.0)
[liblfds] / liblfds / liblfds7.0.0 / test / src / test_lfds700_freelist_rapid_popping_and_pushing.c
1 /***** includes *****/
2 #include "internal.h"
3
4 /***** structs *****/
5 struct test_state
6 {
7   struct lfds700_freelist_state
8     *fs;
9 };
10
11 struct test_element
12 {
13   struct lfds700_freelist_element
14     fe;
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_freelist_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_list_asu_element
38     *lasue;
39
40   struct lfds700_freelist_state
41     fs;
42
43   struct lfds700_misc_prng_state
44     ps;
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
66   /* TRD : in these tests there is a fundamental antagonism between
67            how much checking/memory clean up that we do and the
68            likelyhood of collisions between threads in their lock-free
69            operations
70
71            the lock-free operations are very quick; if we do anything
72            much at all between operations, we greatly reduce the chance
73            of threads colliding
74
75            so we have some tests which do enough checking/clean up that
76            they can tell the freelist is valid and don't leak memory
77            and here, this test now is one of those which does minimal
78            checking - in fact, the nature of the test is that you can't
79            do any real checking - but goes very quickly
80
81            what we do is create a small freelist and then run one thread
82            per CPU, where each thread simply pushes and then immediately
83            pops
84
85            the test runs for ten seconds
86
87            after the test is done, the only check we do is to traverse
88            the freelist, checking for loops and ensuring the number of
89            elements is correct
90   */
91
92   internal_display_test_name( "Rapid popping and pushing (10 seconds)" );
93
94   lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
95
96   lfds700_misc_prng_init( &ps );
97
98   lfds700_freelist_init_valid_on_current_logical_core( &fs, NULL );
99
100   ts = util_malloc_wrapper( sizeof(struct test_state) * number_logical_processors );
101
102   for( loop = 0 ; loop < number_logical_processors ; loop++ )
103     (ts+loop)->fs = &fs;
104
105   thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
106
107   // TRD : we need one element per thread
108   te_array = util_aligned_malloc( sizeof(struct test_element) * number_logical_processors, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
109
110   for( loop = 0 ; loop < number_logical_processors ; loop++ )
111   {
112     LFDS700_FREELIST_SET_VALUE_IN_ELEMENT( (te_array+loop)->fe, te_array+loop );
113     lfds700_freelist_push( &fs, &(te_array+loop)->fe, &ps );
114   }
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_rapid_popping_and_pushing, 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   vi.min_elements = vi.max_elements = number_logical_processors;
144
145   lfds700_freelist_query( &fs, LFDS700_STACK_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
146
147   lfds700_freelist_cleanup( &fs, NULL );
148
149   util_aligned_free( te_array );
150
151   free( ts );
152
153   // TRD : print the test result
154   internal_display_test_result( 1, "freelist", dvs );
155
156   return;
157 }
158
159
160
161
162
163 /****************************************************************************/
164 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_rapid_popping_and_pushing( void *util_thread_starter_thread_state )
165 {
166   lfds700_pal_uint_t
167     time_loop = 0;
168
169   struct lfds700_freelist_element
170     *fe;
171
172   struct lfds700_misc_prng_state
173     ps;
174
175   struct test_state
176     *ts;
177
178   struct util_thread_starter_thread_state
179     *tsts;
180
181   time_t
182     current_time,
183     start_time;
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   util_thread_starter_ready_and_wait( tsts );
195
196   current_time = start_time = time( NULL );
197
198   while( current_time < start_time + TEST_DURATION_IN_SECONDS )
199   {
200     lfds700_freelist_pop( ts->fs, &fe, &ps );
201     lfds700_freelist_push( ts->fs, fe, &ps );
202
203     if( time_loop++ == TIME_LOOP_COUNT )
204     {
205       time_loop = 0;
206       time( &current_time );
207     }
208   }
209
210   LFDS700_MISC_BARRIER_STORE;
211
212   lfds700_misc_force_store();
213
214   return( (test_pal_thread_return_t) EXIT_SUCCESS );
215 }
216