2 #define LFDS700_MISC_VERSION_STRING "7.0.0"
3 #define LFDS700_MISC_VERSION_INTEGER 700
6 #define NULL ( (void *) 0 )
13 #define LFDS700_MISC_ABSTRACTION_BACKOFF_INITIAL_VALUE 0
14 #define LFDS700_MISC_PRNG_MAX ( (lfds700_pal_uint_t) -1 )
15 #define LFDS700_MISC_DELIBERATELY_CRASH { char *c = 0; *c = 0; }
16 #define LFDS700_MISC_PRNG_SEED 0x0a34655d34c092feULL
17 /* TRD : from an on-line hardware RNG, using atmospheric noise
18 the URL eblow will generate another 16 random hex digits (e.g. a 64-bit number) and is
19 the RNG used to generate the number above (0x0a34655d34c092fe)
20 http://www.random.org/integers/?num=16&min=0&max=15&col=1&base=16&format=plain&rnd=new
22 this seed is a fixed seed which is used for the slow, high quality PRNG,
23 which in turn is used when thread start to generate a single high quality seed
24 for the fast, low quality PRNG used for the CAS exponential backoff
27 #if( LFDS700_PAL_ALIGN_SINGLE_POINTER == 4 ) // TRD : any 32-bit platform
28 // TRD : PRNG is a 32-bit xorshift, numbers suggested by George Marsaglia, in his paper http://www.jstatsoft.org/v08/i14/paper
29 #define LFDS700_MISC_PRNG_GENERATE( pointer_to_lfds700_misc_prng_state ) ( (pointer_to_lfds700_misc_prng_state)->prng_state ^= (pointer_to_lfds700_misc_prng_state)->prng_state >> 13, (pointer_to_lfds700_misc_prng_state)->prng_state ^= (pointer_to_lfds700_misc_prng_state)->prng_state << 17, (pointer_to_lfds700_misc_prng_state)->prng_state ^= (pointer_to_lfds700_misc_prng_state)->prng_state >> 5 )
32 #if( LFDS700_PAL_ALIGN_SINGLE_POINTER == 8 ) // TRD : any 64-bit platform
33 // TRD : PRNG is 64-bit xorshift (xorshift64*), from Sebastiano Vigna (vigna at acm dot org), http://creativecommons.org/publicdomain/zero/1.0/
34 #define LFDS700_MISC_PRNG_GENERATE( pointer_to_lfds700_misc_prng_state ) ( (pointer_to_lfds700_misc_prng_state)->prng_state ^= (pointer_to_lfds700_misc_prng_state)->prng_state >> 12, (pointer_to_lfds700_misc_prng_state)->prng_state ^= (pointer_to_lfds700_misc_prng_state)->prng_state << 25, (pointer_to_lfds700_misc_prng_state)->prng_state ^= (pointer_to_lfds700_misc_prng_state)->prng_state >> 27, (pointer_to_lfds700_misc_prng_state)->prng_state *= 2685821657736338717LL )
37 #if( !defined LFDS700_PAL_ATOMIC_CAS )
38 #define LFDS700_PAL_NO_ATOMIC_CAS
40 // TRD : lfds700_pal_atom_t volatile *destination, lfds700_pal_atom_t *compare, lfds700_pal_atom_t new_destination, enum lfds700_misc_cas_strength cas_strength, char unsigned result
42 #define LFDS700_PAL_ATOMIC_CAS( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result ) \
44 LFDS700_PAL_ASSERT( !"LFDS700_PAL_ATOMIC_CAS not implemented for this platform." ); \
45 LFDS700_MISC_DELIBERATELY_CRASH; \
46 (result) = (char unsigned) 1; \
50 #if( !defined LFDS700_PAL_ATOMIC_DWCAS )
51 #define LFDS700_PAL_NO_ATOMIC_DWCAS
53 // TRD : lfds700_pal_atom_t volatile (*destination)[2], lfds700_pal_atom_t (*compare)[2], lfds700_pal_atom_t (*new_destination)[2], enum lfds700_misc_cas_strength cas_strength, unsigned char result
55 #define LFDS700_PAL_ATOMIC_DWCAS( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result ) \
57 LFDS700_PAL_ASSERT( !"LFDS700_PAL_ATOMIC_DWCAS not implemented for this platform." ); \
58 LFDS700_MISC_DELIBERATELY_CRASH; \
59 (result) = (char unsigned) 1; \
63 #if( !defined LFDS700_PAL_ATOMIC_EXCHANGE )
64 #define LFDS700_PAL_NO_ATOMIC_EXCHANGE
65 // TRD : lfds700_pal_atom_t volatile *destination, lfds700_pal_atom_t *exchange
66 #define LFDS700_PAL_ATOMIC_EXCHANGE( pointer_to_destination, pointer_to_exchange ) \
68 LFDS700_PAL_ASSERT( !"LFDS700_PAL_ATOMIC_EXCHANGE not implemented for this platform." ); \
69 LFDS700_MISC_DELIBERATELY_CRASH; \
73 #if( defined LFDS700_PAL_NO_COMPILER_BARRIERS )
74 #define LFDS700_MISC_BARRIER_LOAD ( LFDS700_PAL_BARRIER_PROCESSOR_LOAD )
75 #define LFDS700_MISC_BARRIER_STORE ( LFDS700_PAL_BARRIER_PROCESSOR_STORE )
76 #define LFDS700_MISC_BARRIER_FULL ( LFDS700_PAL_BARRIER_PROCESSOR_FULL )
78 #define LFDS700_MISC_BARRIER_LOAD ( LFDS700_PAL_BARRIER_COMPILER_LOAD, LFDS700_PAL_BARRIER_PROCESSOR_LOAD, LFDS700_PAL_BARRIER_COMPILER_LOAD )
79 #define LFDS700_MISC_BARRIER_STORE ( LFDS700_PAL_BARRIER_COMPILER_STORE, LFDS700_PAL_BARRIER_PROCESSOR_STORE, LFDS700_PAL_BARRIER_COMPILER_STORE )
80 #define LFDS700_MISC_BARRIER_FULL ( LFDS700_PAL_BARRIER_COMPILER_FULL, LFDS700_PAL_BARRIER_PROCESSOR_FULL, LFDS700_PAL_BARRIER_COMPILER_FULL )
83 #define LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE LFDS700_MISC_BARRIER_LOAD
85 #if( defined LFDS700_PAL_NO_ATOMIC_CAS )
86 #define LFDS700_MISC_ATOMIC_SUPPORT_CAS 0
88 #define LFDS700_MISC_ATOMIC_SUPPORT_CAS 1
91 #if( defined LFDS700_PAL_NO_ATOMIC_DWCAS )
92 #define LFDS700_MISC_ATOMIC_SUPPORT_DWCAS 0
94 #define LFDS700_MISC_ATOMIC_SUPPORT_DWCAS 1
97 #if( defined LFDS700_PAL_NO_ATOMIC_EXCHANGE )
98 #define LFDS700_MISC_ATOMIC_SUPPORT_EXCHANGE 0
100 #define LFDS700_MISC_ATOMIC_SUPPORT_EXCHANGE 1
104 enum lfds700_misc_cas_strength
106 // TRD : yes, weak is 1 (one) - blame GCC!
107 LFDS700_MISC_CAS_STRENGTH_WEAK = 1,
108 LFDS700_MISC_CAS_STRENGTH_STRONG = 0
111 enum lfds700_misc_validity
113 LFDS700_MISC_VALIDITY_VALID,
114 LFDS700_MISC_VALIDITY_INVALID_LOOP,
115 LFDS700_MISC_VALIDITY_INVALID_MISSING_ELEMENTS,
116 LFDS700_MISC_VALIDITY_INVALID_ADDITIONAL_ELEMENTS,
117 LFDS700_MISC_VALIDITY_INVALID_TEST_DATA,
118 LFDS700_MISC_VALIDITY_INVALID_ORDER
121 enum lfds700_misc_flag
123 LFDS700_MISC_FLAG_LOWERED,
124 LFDS700_MISC_FLAG_RAISED
127 enum lfds700_misc_query
129 LFDS700_MISC_QUERY_GET_EXPONENTIAL_BACKOFF_TIMESLOT_LENGTH_IN_LOOP_ITERATIONS_FOR_CAS,
130 LFDS700_MISC_QUERY_SET_EXPONENTIAL_BACKOFF_TIMESLOT_LENGTH_IN_LOOP_ITERATIONS_FOR_CAS,
131 LFDS700_MISC_QUERY_GET_EXPONENTIAL_BACKOFF_TIMESLOT_LENGTH_IN_LOOP_ITERATIONS_FOR_DWCAS,
132 LFDS700_MISC_QUERY_SET_EXPONENTIAL_BACKOFF_TIMESLOT_LENGTH_IN_LOOP_ITERATIONS_FOR_DWCAS,
133 LFDS700_MISC_QUERY_GET_BUILD_AND_VERSION_STRING
137 struct lfds700_misc_globals
140 exponential_backoff_timeslot_length_in_loop_iterations_for_cas,
141 exponential_backoff_timeslot_length_in_loop_iterations_for_dwcas;
144 struct lfds700_misc_prng_state
149 // TRD : here to be on the same cache-line as prng_state, and so all are obtained from one cache-line read
151 local_copy_of_global_exponential_backoff_timeslot_length_in_loop_iterations_for_cas,
152 local_copy_of_global_exponential_backoff_timeslot_length_in_loop_iterations_for_dwcas;
155 struct lfds700_misc_validation_info
162 /***** externs *****/
163 extern struct lfds700_misc_globals
164 lfds700_misc_globals;
166 /***** public prototypes *****/
167 void lfds700_misc_library_init_valid_on_current_logical_core( void );
168 // TRD : used in conjunction with the #define LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE
169 void lfds700_misc_library_cleanup( void );
171 static LFDS700_PAL_INLINE void lfds700_misc_force_store( void );
173 void lfds700_misc_prng_init( struct lfds700_misc_prng_state *ps );
175 void lfds700_misc_query( enum lfds700_misc_query query_type, void *query_input, void *query_output );
177 /***** public in-line functions *****/
178 #pragma prefast( disable : 28112, "blah" )
180 static LFDS700_PAL_INLINE void lfds700_misc_force_store()
185 lfds700_pal_atom_t volatile LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
188 LFDS700_PAL_ATOMIC_EXCHANGE( &destination, &exchange );