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