]> pd.if.org Git - liblfds/blob - liblfds/liblfds7.1.0/test_and_benchmark/libtest/src/libtest_tests/libtest_tests_porting_abstraction_layer_atomic_cas.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_porting_abstraction_layer_atomic_cas.c
1 /***** includes *****/
2 #include "libtest_tests_internal.h"
3
4 /***** structs *****/
5 struct libtest_tests_pal_atomic_cas_state
6 {
7   lfds710_pal_uint_t
8     local_counter;
9
10   lfds710_pal_uint_t volatile
11     *shared_counter;
12 };
13
14 /***** private prototyps *****/
15 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_cas( void *libtest_threadset_per_thread_state );
16
17
18
19
20
21 /****************************************************************************/
22 void libtest_tests_pal_atomic_cas( struct lfds710_list_asu_state *list_of_logical_processors, struct libshared_memory_state *ms, enum lfds710_misc_validity *dvs )
23 {
24   lfds710_pal_uint_t volatile LFDS710_PAL_ALIGN(LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES)
25     shared_counter;
26
27   lfds710_pal_uint_t
28     local_total = 0;
29
30   lfds710_pal_uint_t
31     loop = 0,
32     number_logical_processors;
33
34   struct lfds710_list_asu_element
35     *lasue = NULL;
36
37   struct libtest_logical_processor
38     *lp;
39
40   struct libtest_threadset_per_thread_state
41     *pts;
42
43   struct libtest_threadset_state
44     ts;
45
46   struct libtest_tests_pal_atomic_cas_state
47     *atcs;
48
49   LFDS710_PAL_ASSERT( list_of_logical_processors != NULL );
50   LFDS710_PAL_ASSERT( ms != NULL );
51   LFDS710_PAL_ASSERT( dvs != NULL );
52
53   /* TRD : here we test pal_cas
54
55            we run one thread per CPU
56            we use pal_cas() to increment a shared counter
57            every time a thread successfully increments the counter,
58            it increments a thread local counter
59            the threads run for ten seconds
60            after the threads finish, we total the local counters
61            they should equal the shared counter
62   */
63
64   // TRD : allocate
65   lfds710_list_asu_query( list_of_logical_processors, LFDS710_LIST_ASU_QUERY_GET_POTENTIALLY_INACCURATE_COUNT, NULL, (void **) &number_logical_processors );
66   pts = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct libtest_threadset_per_thread_state) * number_logical_processors, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
67   atcs = libshared_memory_alloc_from_unknown_node( ms, sizeof(struct libtest_tests_pal_atomic_cas_state) * number_logical_processors, LFDS710_PAL_ATOMIC_ISOLATION_IN_BYTES );
68
69   shared_counter = 0;
70
71   for( loop = 0 ; loop < number_logical_processors ; loop++ )
72   {
73     (atcs+loop)->shared_counter = &shared_counter;
74     (atcs+loop)->local_counter = 0;
75   }
76
77   libtest_threadset_init( &ts, NULL );
78
79   loop = 0;
80
81   while( LFDS710_LIST_ASU_GET_START_AND_THEN_NEXT(*list_of_logical_processors,lasue) )
82   {
83     lp = LFDS710_LIST_ASU_GET_VALUE_FROM_ELEMENT( *lasue );
84     libtest_threadset_add_thread( &ts, &pts[loop], lp, thread_cas, atcs+loop );
85     loop++;
86   }
87
88   LFDS710_MISC_BARRIER_STORE;
89
90   lfds710_misc_force_store();
91
92   // TRD : run the test
93   libtest_threadset_run( &ts );
94
95   libtest_threadset_cleanup( &ts );
96
97   // TRD : validate
98   LFDS710_MISC_BARRIER_LOAD;
99
100   for( loop = 0 ; loop < number_logical_processors ; loop++ )
101     local_total += (atcs+loop)->local_counter;
102
103   if( local_total == shared_counter )
104     *dvs = LFDS710_MISC_VALIDITY_VALID;
105
106   if( local_total != shared_counter )
107     *dvs = LFDS710_MISC_VALIDITY_INVALID_TEST_DATA;
108
109   return;
110 }
111
112
113
114
115
116 /****************************************************************************/
117 static libshared_pal_thread_return_t LIBSHARED_PAL_THREAD_CALLING_CONVENTION thread_cas( void *libtest_threadset_per_thread_state )
118 {
119   char unsigned 
120     result;
121
122   lfds710_pal_uint_t
123     loop = 0;
124
125   lfds710_pal_uint_t LFDS710_PAL_ALIGN(LFDS710_PAL_ALIGN_SINGLE_POINTER)
126     exchange,
127     compare;
128
129   struct libtest_tests_pal_atomic_cas_state
130     *atcs;
131
132   struct libtest_threadset_per_thread_state
133     *pts;
134
135   LFDS710_MISC_BARRIER_LOAD;
136
137   LFDS710_PAL_ASSERT( libtest_threadset_per_thread_state != NULL );
138
139   pts = (struct libtest_threadset_per_thread_state *) libtest_threadset_per_thread_state;
140   atcs = LIBTEST_THREADSET_GET_USER_STATE_FROM_PER_THREAD_STATE( *pts );
141
142   LFDS710_MISC_BARRIER_LOAD;
143
144   libtest_threadset_thread_ready_and_wait( pts );
145
146   while( loop++ < 10000000 )
147   {
148     compare = *atcs->shared_counter;
149
150     do
151     {
152       exchange = compare + 1;
153       LFDS710_PAL_ATOMIC_CAS( atcs->shared_counter, &compare, exchange, LFDS710_MISC_CAS_STRENGTH_WEAK, result );
154     }
155     while( result == 0 );
156
157     atcs->local_counter++;
158   }
159
160   LFDS710_MISC_BARRIER_STORE;
161
162   lfds710_misc_force_store();
163
164   return LIBSHARED_PAL_THREAD_RETURN_CAST(RETURN_SUCCESS);
165 }
166