]> granicus.if.org Git - libatomic_ops/commitdiff
Fix test_atomic failure caused unaligned AO_double_t access on x86
authorIvan Maidanski <ivmai@mail.ru>
Tue, 24 Jan 2017 19:46:57 +0000 (22:46 +0300)
committerIvan Maidanski <ivmai@mail.ru>
Mon, 6 Feb 2017 12:55:53 +0000 (15:55 +0300)
(Cherry-pick commit c386add from 'release-7_4' branch.)

The failure is caused by violation of an assertion that checks
AO_double_t variable is 8-byte aligned on x86.

* doc/README.txt (AO_double_t): Add note about required alignment.
* src/atomic_ops/sysdeps/standard_ao_double_t.h (AO_double_t): Add
comment about alignment.
* src/atomic_ops_stack.h (AO_stack_t): Likewise.
* tests/test_atomic.template (test_atomicXX): Define w
local variable as static (as otherwise, e.g., it could have 4-byte
alignment on x86); add comment.
* tests/test_atomic_include.h: Regenerate.

doc/README.txt
src/atomic_ops/sysdeps/standard_ao_double_t.h
src/atomic_ops_stack.h
tests/test_atomic.template
tests/test_atomic_include.h

index 9fab3bcbe9604c9f49d205f76bd66773d626f5f5..88122736856aea3081c12b41be13fbbd69b7497b 100644 (file)
@@ -133,6 +133,16 @@ both of type AO_t.  For compare_and_swap_double, we compare against
 the val1 field.  AO_double_t exists only if AO_HAVE_double_t
 is defined.
 
+Please note that AO_double_t (and AO_stack_t) variables should be properly
+aligned (8-byte alignment on 32-bit targets, 16-byte alignment on 64-bit ones)
+otherwise the behavior of a double-wide atomic primitive might be undefined
+(or an assertion violation might occur) if such a misaligned variable is
+passed (as a reference) to the primitive.  Global and static variables should
+already have proper alignment automatically but automatic variables (i.e.
+located on the stack) might be misaligned because the stack might be
+word-aligned (e.g. 4-byte stack alignment is the default one for x86).
+Luckily, stack-allocated AO variables is a rare case in practice.
+
 ORDERING CONSTRAINTS:
 
 Each operation name also includes a suffix that specifies the associated
index 95803f21369dbbe1f943dbaa8206053cdd7b6012..3a9b00f709be0283e5b6194c5d82ef9c5287c95c 100644 (file)
@@ -23,5 +23,11 @@ typedef union {
 } AO_double_t;
 
 #define AO_HAVE_double_t
+
+/* Note: AO_double_t volatile variables are not intended to be local    */
+/* ones (at least those which are passed to AO double-wide primitives   */
+/* as the first argument), otherwise it is the client responsibility to */
+/* ensure they have double-word alignment.                              */
+
 #define AO_val1 AO_parts.AO_v1
 #define AO_val2 AO_parts.AO_v2
index 6c8b5bb6e95f180a3c0adcda45b1296bab41efd2..58a9b230218b71cffd91c36522abeb7a8c6f8360 100644 (file)
@@ -156,6 +156,9 @@ AO_INLINE void AO_stack_init(AO_stack_t *list)
 
 typedef volatile AO_double_t AO_stack_t;
 /* AO_val1 is version, AO_val2 is pointer.      */
+/* Note: AO_stack_t variables are not intended to be local ones,        */
+/* otherwise it is the client responsibility to ensure they have        */
+/* double-word alignment.                                               */
 
 #define AO_STACK_INITIALIZER {0}
 
index a20edd7679b0050e8618d8371af04e4bcf51d25d..db602675d254231adf71859afa093f73a1bc23cb 100644 (file)
@@ -26,7 +26,7 @@ void test_atomicXX(void)
     AO_TS_t z = AO_TS_INITIALIZER;
 # endif
 # if defined(AO_HAVE_double_t)
-    AO_double_t w;
+    static AO_double_t w; /* static to avoid misalignment */
     w.AO_val1 = 0;
     w.AO_val2 = 0;
 # endif
index 2ab5a93c5ffdbf617a6999463b98aa246ce05c73..4a300e35ee14a78051e260b52cebb56ab6b522a7 100644 (file)
@@ -26,7 +26,7 @@ void test_atomic(void)
     AO_TS_t z = AO_TS_INITIALIZER;
 # endif
 # if defined(AO_HAVE_double_t)
-    AO_double_t w;
+    static AO_double_t w; /* static to avoid misalignment */
     w.AO_val1 = 0;
     w.AO_val2 = 0;
 # endif
@@ -230,7 +230,7 @@ void test_atomic_release(void)
     AO_TS_t z = AO_TS_INITIALIZER;
 # endif
 # if defined(AO_HAVE_double_t)
-    AO_double_t w;
+    static AO_double_t w; /* static to avoid misalignment */
     w.AO_val1 = 0;
     w.AO_val2 = 0;
 # endif
@@ -434,7 +434,7 @@ void test_atomic_acquire(void)
     AO_TS_t z = AO_TS_INITIALIZER;
 # endif
 # if defined(AO_HAVE_double_t)
-    AO_double_t w;
+    static AO_double_t w; /* static to avoid misalignment */
     w.AO_val1 = 0;
     w.AO_val2 = 0;
 # endif
@@ -638,7 +638,7 @@ void test_atomic_read(void)
     AO_TS_t z = AO_TS_INITIALIZER;
 # endif
 # if defined(AO_HAVE_double_t)
-    AO_double_t w;
+    static AO_double_t w; /* static to avoid misalignment */
     w.AO_val1 = 0;
     w.AO_val2 = 0;
 # endif
@@ -842,7 +842,7 @@ void test_atomic_write(void)
     AO_TS_t z = AO_TS_INITIALIZER;
 # endif
 # if defined(AO_HAVE_double_t)
-    AO_double_t w;
+    static AO_double_t w; /* static to avoid misalignment */
     w.AO_val1 = 0;
     w.AO_val2 = 0;
 # endif
@@ -1046,7 +1046,7 @@ void test_atomic_full(void)
     AO_TS_t z = AO_TS_INITIALIZER;
 # endif
 # if defined(AO_HAVE_double_t)
-    AO_double_t w;
+    static AO_double_t w; /* static to avoid misalignment */
     w.AO_val1 = 0;
     w.AO_val2 = 0;
 # endif
@@ -1250,7 +1250,7 @@ void test_atomic_release_write(void)
     AO_TS_t z = AO_TS_INITIALIZER;
 # endif
 # if defined(AO_HAVE_double_t)
-    AO_double_t w;
+    static AO_double_t w; /* static to avoid misalignment */
     w.AO_val1 = 0;
     w.AO_val2 = 0;
 # endif
@@ -1454,7 +1454,7 @@ void test_atomic_acquire_read(void)
     AO_TS_t z = AO_TS_INITIALIZER;
 # endif
 # if defined(AO_HAVE_double_t)
-    AO_double_t w;
+    static AO_double_t w; /* static to avoid misalignment */
     w.AO_val1 = 0;
     w.AO_val2 = 0;
 # endif