]> pd.if.org Git - liblfds/blob - liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_stack_popping.c
Initial import (all versions, including the new 7.1.0)
[liblfds] / liblfds / liblfds7.1.0 / test_and_benchmark / libtest / src / libtest_tests / libtest_tests_stack_popping.c
1 /***** includes *****/
2 #include "libtest_tests_internal.h"
3
4 /***** structs *****/
5 struct test_per_thread_state
6 {
7   struct lfds710_stack_state
8     *ss;
9 };
10
11 struct test_element
12 {
13   struct lfds710_stack_element
14     se;
15
16   enum flag
17     popped_flag;
18 };
19
20 /***** private prototypes *****/
21 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_popping( void *libtest_threadset_per_thread_state );
22
23
24
25
26
27 /****************************************************************************/
28 void libtest_tests_stack_popping( struct lfds710_list_asu_state *list_of_logical_processors, struct libshared_memory_state *ms, enum lfds710_misc_validity *dvs )
29 {
30   lfds710_pal_uint_t
31     loop = 0,
32     number_elements,
33     number_logical_processors;
34
35   struct lfds710_stack_state
36     ss;
37
38   struct lfds710_list_asu_element
39     *lasue = NULL;
40
41   struct lfds710_misc_validation_info
42     vi = { 0, 0 };
43
44   struct libtest_logical_processor
45     *lp;
46
47   struct libtest_threadset_per_thread_state
48     *pts;
49
50   struct libtest_threadset_state
51     ts;
52
53   struct test_element
54     *te_array;
55
56   struct test_per_thread_state
57     *tpts;
58
59   LFDS710_PAL_ASSERT( list_of_logical_processors != NULL );
60   LFDS710_PAL_ASSERT( ms != NULL );
61   LFDS710_PAL_ASSERT( dvs != NULL );
62
63   /* TRD : we create a stack with as many elements as possible elements
64
65            the creation function runs in a single thread and creates
66            and pushes those elements onto the stack
67
68            each element contains a void pointer to the container test element
69
70            we then run one thread per CPU
71            where each thread loops, popping as quickly as possible
72            each test element has a flag which indicates it has been popped
73
74            the threads run till the source stack is empty
75
76            we then check the test elements
77            every element should have been popped
78
79            then tidy up
80   */
81
82   *dvs = LFDS710_MISC_VALIDITY_VALID;
83
84   // TRD : allocate
85   lfds710_list_asu_query( list_of_logical_processors, LFDS710_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
86   tpts = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct test_per_thread_state) * number_logical_processors, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
87   pts = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct libtest_threadset_per_thread_state) * number_logical_processors, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
88   te_array = libshared_memory_alloc_largest_possible_array_from_unknown_node( ms, sizeof(struct test_element), LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES, &number_elements );
89
90   lfds710_stack_init_valid_on_current_logical_core( &ss, NULL );
91
92   for( loop = 0 ; loop < number_elements ; loop++ )
93   {
94     (te_array+loop)->popped_flag = LOWERED;
95     LFDS710_STACK_SET_VALUE_IN_ELEMENT( (te_array+loop)->se, te_array+loop );
96     lfds710_stack_push( &ss, &(te_array+loop)->se );
97   }
98
99   libtest_threadset_init( &ts, NULL );
100
101   loop = 0;
102
103   while( LFDS710_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors, lasue) )
104   {
105     lp = LFDS710_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
106     tpts[loop].ss = &ss;
107
108     libtest_threadset_add_thread( &ts, &pts[loop], lp, thread_popping, &tpts[loop] );
109
110     loop++;
111   }
112
113   LFDS710_MISC_BARRIER_STORE;
114
115   lfds710_misc_force_store();
116
117   // TRD : run the test
118   libtest_threadset_run( &ts );
119
120   libtest_threadset_cleanup( &ts );
121
122   // TRD : validate
123   LFDS710_MISC_BARRIER_LOAD;
124
125   lfds710_stack_query( &ss, LFDS710_STACK_QUERY_SINGLETHREADED_VALIDATE, &vi, dvs );
126
127   // TRD : now we check each element has popped_flag set to RAISED
128   for( loop = 0 ; loop < number_elements ; loop++ )
129     if( (te_array+loop)->popped_flag == LOWERED )
130       *dvs = LFDS710_MISC_VALIDITY_INVALID_TEST_DATA;
131
132   // TRD : cleanup
133   lfds710_stack_cleanup( &ss, NULL );
134
135   return;
136 }
137
138
139
140
141
142 /****************************************************************************/
143 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_popping( void *libtest_threadset_per_thread_state )
144 {
145   struct lfds710_stack_element
146     *se;
147
148   struct test_per_thread_state
149     *tpts;
150
151   struct libtest_threadset_per_thread_state
152     *pts;
153
154   struct test_element
155     *te;
156
157   LFDS710_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;
158
159   LFDS710_PAL_ASSERT( libtest_threadset_per_thread_state != NULL );
160
161   pts = (struct libtest_threadset_per_thread_state *) libtest_threadset_per_thread_state;
162
163   tpts = LIBTEST_THREADSET_GET_USER_STATE_FROM_PER_THREAD_STATE( *pts );
164
165   libtest_threadset_thread_ready_and_wait( pts );
166
167   while( lfds710_stack_pop(tpts->ss, &se) )
168   {
169     te = LFDS710_STACK_GET_VALUE_FROM_ELEMENT( *se );
170     te->popped_flag = RAISED;
171   }
172
173   LFDS710_MISC_BARRIER_STORE;
174
175   lfds710_misc_force_store();
176
177   return LIBSHARED_PAL_THREAD_RETURN_CAST(RETURN_SUCCESS);
178 }
179