]> pd.if.org Git - liblfds/blob - liblfds/liblfds7.0.0/liblfds700/inc/liblfds700/lfds700_misc.h
Initial import (all versions, including the new 7.1.0)
[liblfds] / liblfds / liblfds7.0.0 / liblfds700 / inc / liblfds700 / lfds700_misc.h
1 /***** defines *****/
2 #define LFDS700_MISC_VERSION_STRING   "7.0.0"
3 #define LFDS700_MISC_VERSION_INTEGER  700
4
5 #ifndef NULL
6   #define NULL ( (void *) 0 )
7 #endif
8
9 #define POINTER   0
10 #define COUNTER   1
11 #define PAC_SIZE  2
12
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
21
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
25   */
26
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 )
30 #endif
31
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 )
35 #endif
36
37 #if( !defined LFDS700_PAL_ATOMIC_CAS )
38   #define LFDS700_PAL_NO_ATOMIC_CAS
39
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
41
42   #define LFDS700_PAL_ATOMIC_CAS( pointer_to_destination, pointer_to_compare, new_destination, cas_strength, result )  \
43   {                                                                                                                    \
44     LFDS700_PAL_ASSERT( !"LFDS700_PAL_ATOMIC_CAS not implemented for this platform." );                                \
45     LFDS700_MISC_DELIBERATELY_CRASH;                                                                                   \
46     (result) = (char unsigned) 1;                                                                                      \
47   }
48 #endif
49
50 #if( !defined LFDS700_PAL_ATOMIC_DWCAS )
51   #define LFDS700_PAL_NO_ATOMIC_DWCAS
52
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
54
55   #define LFDS700_PAL_ATOMIC_DWCAS( pointer_to_destination, pointer_to_compare, pointer_to_new_destination, cas_strength, result )  \
56   {                                                                                                                                 \
57     LFDS700_PAL_ASSERT( !"LFDS700_PAL_ATOMIC_DWCAS not implemented for this platform." );                                           \
58     LFDS700_MISC_DELIBERATELY_CRASH;                                                                                                \
59     (result) = (char unsigned) 1;                                                                                                   \
60   }
61 #endif
62
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 )          \
67   {                                                                                           \
68     LFDS700_PAL_ASSERT( !"LFDS700_PAL_ATOMIC_EXCHANGE not implemented for this platform." );  \
69     LFDS700_MISC_DELIBERATELY_CRASH;                                                          \
70   }
71 #endif
72
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  )
77 #else
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  )
81 #endif
82
83 #define LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE  LFDS700_MISC_BARRIER_LOAD
84
85 #if( defined LFDS700_PAL_NO_ATOMIC_CAS )
86   #define LFDS700_MISC_ATOMIC_SUPPORT_CAS 0
87 #else
88   #define LFDS700_MISC_ATOMIC_SUPPORT_CAS 1
89 #endif
90
91 #if( defined LFDS700_PAL_NO_ATOMIC_DWCAS )
92   #define LFDS700_MISC_ATOMIC_SUPPORT_DWCAS 0
93 #else
94   #define LFDS700_MISC_ATOMIC_SUPPORT_DWCAS 1
95 #endif
96
97 #if( defined LFDS700_PAL_NO_ATOMIC_EXCHANGE )
98   #define LFDS700_MISC_ATOMIC_SUPPORT_EXCHANGE 0
99 #else
100   #define LFDS700_MISC_ATOMIC_SUPPORT_EXCHANGE 1
101 #endif
102
103 /***** enums *****/
104 enum lfds700_misc_cas_strength
105 {
106   // TRD : yes, weak is 1 (one) - blame GCC!
107   LFDS700_MISC_CAS_STRENGTH_WEAK   = 1,
108   LFDS700_MISC_CAS_STRENGTH_STRONG = 0
109 };
110
111 enum lfds700_misc_validity
112 {
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
119 };
120
121 enum lfds700_misc_flag
122 {
123   LFDS700_MISC_FLAG_LOWERED,
124   LFDS700_MISC_FLAG_RAISED
125 };
126
127 enum lfds700_misc_query
128 {
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
134 };
135
136 /***** struct *****/
137 struct lfds700_misc_globals
138 {
139   lfds700_pal_atom_t
140     exponential_backoff_timeslot_length_in_loop_iterations_for_cas,
141     exponential_backoff_timeslot_length_in_loop_iterations_for_dwcas;
142 };
143
144 struct lfds700_misc_prng_state
145 {
146   lfds700_pal_uint_t
147     prng_state;
148
149   // TRD : here to be on the same cache-line as prng_state, and so all are obtained from one cache-line read
150   lfds700_pal_atom_t
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;
153 };
154
155 struct lfds700_misc_validation_info
156 {
157   lfds700_pal_uint_t
158     min_elements,
159     max_elements;
160 };
161
162 /***** externs *****/
163 extern struct lfds700_misc_globals
164   lfds700_misc_globals;
165
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 );
170
171 static LFDS700_PAL_INLINE void lfds700_misc_force_store( void );
172
173 void lfds700_misc_prng_init( struct lfds700_misc_prng_state *ps );
174
175 void lfds700_misc_query( enum lfds700_misc_query query_type, void *query_input, void *query_output );
176
177 /***** public in-line functions *****/
178 #pragma prefast( disable : 28112, "blah" )
179
180 static LFDS700_PAL_INLINE void lfds700_misc_force_store()
181 {
182   lfds700_pal_uint_t
183     exchange = 0;
184
185   lfds700_pal_atom_t volatile LFDS700_PAL_ALIGN(LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES)
186     destination;
187
188   LFDS700_PAL_ATOMIC_EXCHANGE( &destination, &exchange );
189
190   return;
191 }
192