]> pd.if.org Git - liblfds/blob - liblfds/liblfds7.0.0/test/src/test_lfds700_freelist_popping.c
Initial import (all versions, including the new 7.1.0)
[liblfds] / liblfds / liblfds7.0.0 / test / src / test_lfds700_freelist_popping.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   enum flag
17     popped_flag;
18 };
19
20 /***** private prototypes *****/
21 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping( void *util_thread_starter_thread_state );
22
23
24
25
26
27 /****************************************************************************/
28 void test_lfds700_freelist_popping( 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,
36     number_logical_processors;
37
38   struct lfds700_list_asu_element
39     *lasue;
40
41   struct lfds700_freelist_state
42     fs;
43
44   struct lfds700_misc_prng_state
45     ps;
46
47   struct lfds700_misc_validation_info
48     vi = { 0, 0 };
49
50   struct test_pal_logical_processor
51     *lp;
52
53   struct util_thread_starter_state
54     *tts;
55
56   struct test_element
57     *te_array;
58
59   struct test_state
60     *ts;
61
62   test_pal_thread_state_t
63     *thread_handles;
64
65   assert( list_of_logical_processors != NULL );
66   // TRD : memory_in_megabytes can be any value in its range
67
68   /* TRD : we create a freelist with 1,000,000 elements
69
70            the creation function runs in a single thread and creates
71            and pushes those elements onto the freelist
72
73            each element contains a void pointer to the container test element
74
75            we then run one thread per CPU
76            where each thread loops, popping as quickly as possible
77            each test element has a flag which indicates it has been popped
78
79            the threads run till the source freelist is empty
80
81            we then check the test elements
82            every element should have been popped
83
84            then tidy up
85
86            we have no extra code for CAS/GC as we're only popping
87   */
88
89   internal_display_test_name( "Popping" );
90
91   lfds700_list_asu_query( list_of_logical_processors, LFDS700_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
92
93   lfds700_misc_prng_init( &ps );
94
95   lfds700_freelist_init_valid_on_current_logical_core( &fs, NULL );
96
97   number_elements = ( memory_in_megabytes * ONE_MEGABYTE_IN_BYTES ) / sizeof(struct test_element);
98
99   te_array = util_aligned_malloc( sizeof(struct test_element) * number_elements, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
100
101   for( loop = 0 ; loop < number_elements ; loop++ )
102   {
103     (te_array+loop)->popped_flag = LOWERED;
104     LFDS700_FREELIST_SET_VALUE_IN_ELEMENT( (te_array+loop)->fe, te_array+loop );
105     lfds700_freelist_push( &fs, &(te_array+loop)->fe, &ps );
106   }
107
108   ts = util_aligned_malloc( sizeof(struct test_state) * number_logical_processors, LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES );
109
110   for( loop = 0 ; loop < number_logical_processors ; loop++ )
111     (ts+loop)->fs = &fs;
112
113   thread_handles = util_malloc_wrapper( sizeof(test_pal_thread_state_t) * number_logical_processors );
114
115   util_thread_starter_new( &tts, number_logical_processors );
116
117   LFDS700_MISC_BARRIER_STORE;
118
119   lfds700_misc_force_store();
120
121   loop = 0;
122   lasue = NULL;
123
124   while( LFDS700_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
125   {
126     lp = LFDS700_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
127     util_thread_starter_start( tts, &thread_handles[loop], loop, lp, thread_popping, ts+loop );
128     loop++;
129   }
130
131   util_thread_starter_run( tts );
132
133   for( loop = 0 ; loop < number_logical_processors ; loop++ )
134     test_pal_thread_wait( thread_handles[loop] );
135
136   util_thread_starter_delete( tts );
137
138   free( thread_handles );
139
140   LFDS700_MISC_BARRIER_LOAD;
141
142   lfds700_freelist_query( &fs, LFDS700_FREELIST_QUERY_SINGLETHREADED_VALIDATE, &vi, &dvs );
143
144   // TRD : now we check each element has popped_flag set to RAISED
145   for( loop = 0 ; loop < number_elements ; loop++ )
146     if( (te_array+loop)->popped_flag == LOWERED )
147       dvs = LFDS700_MISC_VALIDITY_INVALID_TEST_DATA;
148
149   // TRD : cleanup
150   lfds700_freelist_cleanup( &fs, NULL );
151   util_aligned_free( ts );
152   util_aligned_free( te_array );
153
154   // TRD : print the test result
155   internal_display_test_result( 1, "freelist", dvs );
156
157   return;
158 }
159
160
161
162
163
164 /****************************************************************************/
165 static test_pal_thread_return_t TEST_PAL_CALLING_CONVENTION thread_popping( void *util_thread_starter_thread_state )
166 {
167   struct lfds700_freelist_element
168     *fe;
169
170   struct lfds700_misc_prng_state
171     ps;
172
173   struct test_element
174     *te;
175
176   struct test_state
177     *ts;
178
179   struct util_thread_starter_thread_state
180     *tsts;
181
182   LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
183
184   assert( util_thread_starter_thread_state != NULL );
185
186   tsts = (struct util_thread_starter_thread_state *) util_thread_starter_thread_state;
187   ts = (struct test_state *) tsts->thread_user_state;
188
189   lfds700_misc_prng_init( &ps );
190
191   util_thread_starter_ready_and_wait( tsts );
192
193   while( lfds700_freelist_pop(ts->fs, &fe, &ps) )
194   {
195     te = LFDS700_FREELIST_GET_VALUE_FROM_ELEMENT( *fe );
196     te->popped_flag = RAISED;
197   }
198
199   LFDS700_MISC_BARRIER_STORE;
200
201   lfds700_misc_force_store();
202
203   return( (test_pal_thread_return_t) EXIT_SUCCESS );
204 }
205