diff mbox

[PATCHv2,libatomic] Avoid misaligned atomic operations

Message ID 1421791829-49022-1-git-send-email-waterman@cs.berkeley.edu
State New
Headers show

Commit Message

Andrew Waterman Jan. 20, 2015, 10:10 p.m. UTC
My original patch only fixed libat_fetch_op; this one applies the same
fix to libat_op_fetch, as well.

When using word-wide CAS to emulate atomic fetch-and-op, addresses should
be word-aligned to avoid exceptions on some targets.

The problem manifested in a new port I'm working on as a failure in test
gcc.dg/atomic/stdatomic-op-1.c, and I've confirmed that this patch
fixes it.  x86_64-unknown-linux still bootstraps, but that is admittedly
of little significance, since it doesn't use these routines.

2015-01-09  Andrew Waterman <waterman@cs.berkeley.edu>

	* fop_n.c (libat_fetch_op): Align address to word boundary.
	(libat_op_fetch): Likewise.
---
 libatomic/fop_n.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

Comments

Richard Henderson Jan. 21, 2015, 5:21 p.m. UTC | #1
On 01/20/2015 02:10 PM, Andrew Waterman wrote:
> 2015-01-09  Andrew Waterman <waterman@cs.berkeley.edu>
> 
> 	* fop_n.c (libat_fetch_op): Align address to word boundary.
> 	(libat_op_fetch): Likewise.

Thanks.  Applied to 4.8, 4.9, and mainline branches.


r~
diff mbox

Patch

diff --git a/libatomic/fop_n.c b/libatomic/fop_n.c
index 307184d..854d648 100644
--- a/libatomic/fop_n.c
+++ b/libatomic/fop_n.c
@@ -112,9 +112,9 @@  SIZE(C2(libat_fetch_,NAME)) (UTYPE *mptr, UTYPE opval, int smodel)
 
   pre_barrier (smodel);
 
-  wptr = (UWORD *)mptr;
-  shift = 0;
-  mask = -1;
+  wptr = (UWORD *)((uintptr_t)mptr & -WORDSIZE);
+  shift = (((uintptr_t)mptr % WORDSIZE) * CHAR_BIT) ^ SIZE(INVERT_MASK);
+  mask = SIZE(MASK) << shift;
 
   wopval = (UWORD)opval << shift;
   woldval = __atomic_load_n (wptr, __ATOMIC_RELAXED);
@@ -136,9 +136,9 @@  SIZE(C3(libat_,NAME,_fetch)) (UTYPE *mptr, UTYPE opval, int smodel)
 
   pre_barrier (smodel);
 
-  wptr = (UWORD *)mptr;
-  shift = 0;
-  mask = -1;
+  wptr = (UWORD *)((uintptr_t)mptr & -WORDSIZE);
+  shift = (((uintptr_t)mptr % WORDSIZE) * CHAR_BIT) ^ SIZE(INVERT_MASK);
+  mask = SIZE(MASK) << shift;
 
   wopval = (UWORD)opval << shift;
   woldval = __atomic_load_n (wptr, __ATOMIC_RELAXED);