including it. Compare_and_swap is otherwise not available.
Defining AO_ASSUME_VISTA will make compare_double_and_swap_double available
as well.
+Please note that MS compiler for x86 does not align AO_double_t on an 8-byte
+boundary, thus to avoid an undefined behavior, an AO_double_t (volatile)
+variable should be declared with AO_DOUBLE_ALIGN attribute if the variable
+reference is passed to an AO primitive (the attribute is not applicable to
+arguments and pointers).
Note that the library is covered by the GNU General Public License, while
the top 2 of these pieces allow use in proprietary code.
AO_t AO_val2;
} AO_double_t;
#define AO_HAVE_double_t
+#define AO_DOUBLE_ALIGN /* empty */
#define AO_DOUBLE_T_INITIALIZER { (AO_t)0, (AO_t)0 }
typedef __m128 double_ptr_storage;
#elif defined(_WIN32) && !defined(__GNUC__)
typedef unsigned __int64 double_ptr_storage;
+# ifdef _MSC_VER
+ /* VC++/x86 does not align __int64 properly by default, thus, */
+ /* causing an undefined behavior or assertions violation in */
+ /* the double-wide atomic primitives. For the proper alignment, */
+ /* all variables of AO_double_t type (in the client code) those */
+ /* address is passed to an AO primitive should be defined with the */
+ /* given attribute. Not a part of double_ptr_storage because the */
+ /* attribute cannot be applied to function parameters. */
+# define AO_DOUBLE_ALIGN __declspec(align(8))
+# endif
#else
typedef unsigned long long double_ptr_storage;
#endif
# define AO_HAVE_DOUBLE_PTR_STORAGE
+#ifndef AO_DOUBLE_ALIGN
+# define AO_DOUBLE_ALIGN /* empty */
+#endif
+
typedef union {
struct { AO_t AO_v1; AO_t AO_v2; } AO_parts;
/* Note that AO_v1 corresponds to the low or the high part of */
/* Object free lists. Ith entry corresponds to objects */
/* of total size 2**i bytes. */
-AO_stack_t AO_free_list[LOG_MAX_SIZE+1];
+AO_stack_t AO_DOUBLE_ALIGN AO_free_list[LOG_MAX_SIZE+1];
/* Break up the chunk, and add it to the object free list for */
/* the given size. We have exclusive access to chunk. */
AO_stack_pop_explicit_aux_acquire(&((l)->AO_ptr), &((l)->AO_aux))
#define AO_HAVE_stack_pop_acquire
+#ifndef AO_DOUBLE_ALIGN
+ /* For AO_stack clients only. */
+# define AO_DOUBLE_ALIGN /* empty */
+#endif
+
# else /* Use fully non-blocking data structure, wide CAS */
#ifndef AO_HAVE_double_t
typedef volatile AO_double_t AO_stack_t;
/* AO_val1 is version, AO_val2 is pointer. */
+/* AO_stack_t variables should have AO_DOUBLE_ALIGN attribute. */
#define AO_STACK_INITIALIZER AO_DOUBLE_T_INITIALIZER
# if defined(AO_HAVE_double_compare_and_swapXX) \
|| defined(AO_HAVE_double_loadXX) \
|| defined(AO_HAVE_double_storeXX)
- AO_double_t old_w;
+ AO_double_t AO_DOUBLE_ALIGN old_w;
AO_double_t new_w;
# endif
# if defined(AO_HAVE_compare_and_swap_doubleXX) \
|| defined(AO_HAVE_compare_double_and_swap_doubleXX) \
|| defined(AO_HAVE_double_compare_and_swapXX)
- AO_double_t w;
+ AO_double_t AO_DOUBLE_ALIGN w;
w.AO_val1 = 0;
w.AO_val2 = 0;
# endif
int data;
} list_element;
-AO_stack_t the_list = AO_STACK_INITIALIZER;
+AO_stack_t AO_DOUBLE_ALIGN the_list = AO_STACK_INITIALIZER;
void add_elements(int n)
{