From 03155c0d2f1fd52ee863dc1059fc662993983fa9 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Tue, 15 Jun 2021 15:28:24 -0400 Subject: [PATCH] Fix: x86 and s390 uatomic: __hp() macro warning with gcc 11 MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The __hp() macro used in the x86 and s390 uatomic code generates the following warning with gcc-11: In file included from ../include/urcu/uatomic.h:27, from ../include/urcu/static/wfcqueue.h:35, from ../include/urcu/wfcqueue.h:133, from workqueue.c:39: workqueue.c: In function ‘workqueue_thread’: ../include/urcu/uatomic/x86.h:155:17: warning: array subscript ‘struct __uatomic_dummy[0]’ is partly outside array bounds of ‘struct cds_wfcq_tail[1]’ [-Warray-bounds] 155 | __asm__ __volatile__( | ^~~~~~~ workqueue.c:184:38: note: while referencing ‘cbs_tmp_tail’ 184 | struct cds_wfcq_tail cbs_tmp_tail; | ^~~~~~~~~~~~ The (previously undocumented) reason for this macro is to allow passing the "void *" parameter as "m" or "+m" operand to the inline assembly. That motivation was explained in commit 53b8ed6836363 ("s390 uatomic arch fix"). The out of bound access is detected by gcc because struct __uatomic_dummy's length is quite large: an array of 10 unsigned long, which is larger than the size pointed to by the void pointer. So rather than using a fixed-size type, cast to a structure containing an array of characters of a size matching the @addr input argument. While we are at it and digging out git archeology, properly document the __hp() macro for posterity. Signed-off-by: Mathieu Desnoyers Change-Id: I785e30661efe48be1806664a1a14fd3c9fdb0a32 --- include/urcu/uatomic/s390.h | 28 ++++++++------ include/urcu/uatomic/x86.h | 76 +++++++++++++++++++------------------ 2 files changed, 56 insertions(+), 48 deletions(-) diff --git a/include/urcu/uatomic/s390.h b/include/urcu/uatomic/s390.h index 62561e0..47b97b1 100644 --- a/include/urcu/uatomic/s390.h +++ b/include/urcu/uatomic/s390.h @@ -61,10 +61,14 @@ extern "C" { #endif /* !COMPILER_HAVE_SHORT_MEM_OPERAND */ -struct __uatomic_dummy { - unsigned long v[10]; -}; -#define __hp(x) ((struct __uatomic_dummy *)(x)) +/* + * The __hp() macro casts the void pointer "x" to a pointer to a structure + * containing an array of char of the specified size. This allows passing the + * @addr arguments of the following inline functions as "m" and "+m" operands + * to the assembly. + */ + +#define __hp(size, x) ((struct { char v[size]; } *)(x)) /* xchg */ @@ -79,8 +83,8 @@ unsigned long _uatomic_exchange(volatile void *addr, unsigned long val, int len) __asm__ __volatile__( "0: cs %0,%2," MEMOP_REF(%3) "\n" " brc 4,0b\n" - : "=&r" (old_val), MEMOP_OUT (__hp(addr)) - : "r" (val), MEMOP_IN (__hp(addr)) + : "=&r" (old_val), MEMOP_OUT (__hp(len, addr)) + : "r" (val), MEMOP_IN (__hp(len, addr)) : "memory", "cc"); return old_val; } @@ -92,8 +96,8 @@ unsigned long _uatomic_exchange(volatile void *addr, unsigned long val, int len) __asm__ __volatile__( "0: csg %0,%2," MEMOP_REF(%3) "\n" " brc 4,0b\n" - : "=&r" (old_val), MEMOP_OUT (__hp(addr)) - : "r" (val), MEMOP_IN (__hp(addr)) + : "=&r" (old_val), MEMOP_OUT (__hp(len, addr)) + : "r" (val), MEMOP_IN (__hp(len, addr)) : "memory", "cc"); return old_val; } @@ -123,8 +127,8 @@ unsigned long _uatomic_cmpxchg(void *addr, unsigned long old, __asm__ __volatile__( " cs %0,%2," MEMOP_REF(%3) "\n" - : "+r" (old_val), MEMOP_OUT (__hp(addr)) - : "r" (_new), MEMOP_IN (__hp(addr)) + : "+r" (old_val), MEMOP_OUT (__hp(len, addr)) + : "r" (_new), MEMOP_IN (__hp(len, addr)) : "memory", "cc"); return old_val; } @@ -133,8 +137,8 @@ unsigned long _uatomic_cmpxchg(void *addr, unsigned long old, { __asm__ __volatile__( " csg %0,%2," MEMOP_REF(%3) "\n" - : "+r" (old), MEMOP_OUT (__hp(addr)) - : "r" (_new), MEMOP_IN (__hp(addr)) + : "+r" (old), MEMOP_OUT (__hp(len, addr)) + : "r" (_new), MEMOP_IN (__hp(len, addr)) : "memory", "cc"); return old; } diff --git a/include/urcu/uatomic/x86.h b/include/urcu/uatomic/x86.h index 2a4ea1c..03a0b2f 100644 --- a/include/urcu/uatomic/x86.h +++ b/include/urcu/uatomic/x86.h @@ -35,10 +35,14 @@ extern "C" { * Derived from AO_compare_and_swap() and AO_test_and_set_full(). */ -struct __uatomic_dummy { - unsigned long v[10]; -}; -#define __hp(x) ((struct __uatomic_dummy *)(x)) +/* + * The __hp() macro casts the void pointer "x" to a pointer to a structure + * containing an array of char of the specified size. This allows passing the + * @addr arguments of the following inline functions as "m" and "+m" operands + * to the assembly. + */ + +#define __hp(size, x) ((struct { char v[size]; } *)(x)) #define _uatomic_set(addr, v) ((void) CMM_STORE_SHARED(*(addr), (v))) @@ -55,7 +59,7 @@ unsigned long __uatomic_cmpxchg(void *addr, unsigned long old, __asm__ __volatile__( "lock; cmpxchgb %2, %1" - : "+a"(result), "+m"(*__hp(addr)) + : "+a"(result), "+m"(*__hp(len, addr)) : "q"((unsigned char)_new) : "memory"); return result; @@ -66,7 +70,7 @@ unsigned long __uatomic_cmpxchg(void *addr, unsigned long old, __asm__ __volatile__( "lock; cmpxchgw %2, %1" - : "+a"(result), "+m"(*__hp(addr)) + : "+a"(result), "+m"(*__hp(len, addr)) : "r"((unsigned short)_new) : "memory"); return result; @@ -77,7 +81,7 @@ unsigned long __uatomic_cmpxchg(void *addr, unsigned long old, __asm__ __volatile__( "lock; cmpxchgl %2, %1" - : "+a"(result), "+m"(*__hp(addr)) + : "+a"(result), "+m"(*__hp(len, addr)) : "r"((unsigned int)_new) : "memory"); return result; @@ -89,7 +93,7 @@ unsigned long __uatomic_cmpxchg(void *addr, unsigned long old, __asm__ __volatile__( "lock; cmpxchgq %2, %1" - : "+a"(result), "+m"(*__hp(addr)) + : "+a"(result), "+m"(*__hp(len, addr)) : "r"((unsigned long)_new) : "memory"); return result; @@ -122,7 +126,7 @@ unsigned long __uatomic_exchange(void *addr, unsigned long val, int len) unsigned char result; __asm__ __volatile__( "xchgb %0, %1" - : "=q"(result), "+m"(*__hp(addr)) + : "=q"(result), "+m"(*__hp(len, addr)) : "0" ((unsigned char)val) : "memory"); return result; @@ -132,7 +136,7 @@ unsigned long __uatomic_exchange(void *addr, unsigned long val, int len) unsigned short result; __asm__ __volatile__( "xchgw %0, %1" - : "=r"(result), "+m"(*__hp(addr)) + : "=r"(result), "+m"(*__hp(len, addr)) : "0" ((unsigned short)val) : "memory"); return result; @@ -142,7 +146,7 @@ unsigned long __uatomic_exchange(void *addr, unsigned long val, int len) unsigned int result; __asm__ __volatile__( "xchgl %0, %1" - : "=r"(result), "+m"(*__hp(addr)) + : "=r"(result), "+m"(*__hp(len, addr)) : "0" ((unsigned int)val) : "memory"); return result; @@ -153,7 +157,7 @@ unsigned long __uatomic_exchange(void *addr, unsigned long val, int len) unsigned long result; __asm__ __volatile__( "xchgq %0, %1" - : "=r"(result), "+m"(*__hp(addr)) + : "=r"(result), "+m"(*__hp(len, addr)) : "0" ((unsigned long)val) : "memory"); return result; @@ -186,7 +190,7 @@ unsigned long __uatomic_add_return(void *addr, unsigned long val, __asm__ __volatile__( "lock; xaddb %1, %0" - : "+m"(*__hp(addr)), "+q" (result) + : "+m"(*__hp(len, addr)), "+q" (result) : : "memory"); return result + (unsigned char)val; @@ -197,7 +201,7 @@ unsigned long __uatomic_add_return(void *addr, unsigned long val, __asm__ __volatile__( "lock; xaddw %1, %0" - : "+m"(*__hp(addr)), "+r" (result) + : "+m"(*__hp(len, addr)), "+r" (result) : : "memory"); return result + (unsigned short)val; @@ -208,7 +212,7 @@ unsigned long __uatomic_add_return(void *addr, unsigned long val, __asm__ __volatile__( "lock; xaddl %1, %0" - : "+m"(*__hp(addr)), "+r" (result) + : "+m"(*__hp(len, addr)), "+r" (result) : : "memory"); return result + (unsigned int)val; @@ -220,7 +224,7 @@ unsigned long __uatomic_add_return(void *addr, unsigned long val, __asm__ __volatile__( "lock; xaddq %1, %0" - : "+m"(*__hp(addr)), "+r" (result) + : "+m"(*__hp(len, addr)), "+r" (result) : : "memory"); return result + (unsigned long)val; @@ -250,7 +254,7 @@ void __uatomic_and(void *addr, unsigned long val, int len) { __asm__ __volatile__( "lock; andb %1, %0" - : "=m"(*__hp(addr)) + : "=m"(*__hp(len, addr)) : "iq" ((unsigned char)val) : "memory"); return; @@ -259,7 +263,7 @@ void __uatomic_and(void *addr, unsigned long val, int len) { __asm__ __volatile__( "lock; andw %1, %0" - : "=m"(*__hp(addr)) + : "=m"(*__hp(len, addr)) : "ir" ((unsigned short)val) : "memory"); return; @@ -268,7 +272,7 @@ void __uatomic_and(void *addr, unsigned long val, int len) { __asm__ __volatile__( "lock; andl %1, %0" - : "=m"(*__hp(addr)) + : "=m"(*__hp(len, addr)) : "ir" ((unsigned int)val) : "memory"); return; @@ -278,7 +282,7 @@ void __uatomic_and(void *addr, unsigned long val, int len) { __asm__ __volatile__( "lock; andq %1, %0" - : "=m"(*__hp(addr)) + : "=m"(*__hp(len, addr)) : "er" ((unsigned long)val) : "memory"); return; @@ -306,7 +310,7 @@ void __uatomic_or(void *addr, unsigned long val, int len) { __asm__ __volatile__( "lock; orb %1, %0" - : "=m"(*__hp(addr)) + : "=m"(*__hp(len, addr)) : "iq" ((unsigned char)val) : "memory"); return; @@ -315,7 +319,7 @@ void __uatomic_or(void *addr, unsigned long val, int len) { __asm__ __volatile__( "lock; orw %1, %0" - : "=m"(*__hp(addr)) + : "=m"(*__hp(len, addr)) : "ir" ((unsigned short)val) : "memory"); return; @@ -324,7 +328,7 @@ void __uatomic_or(void *addr, unsigned long val, int len) { __asm__ __volatile__( "lock; orl %1, %0" - : "=m"(*__hp(addr)) + : "=m"(*__hp(len, addr)) : "ir" ((unsigned int)val) : "memory"); return; @@ -334,7 +338,7 @@ void __uatomic_or(void *addr, unsigned long val, int len) { __asm__ __volatile__( "lock; orq %1, %0" - : "=m"(*__hp(addr)) + : "=m"(*__hp(len, addr)) : "er" ((unsigned long)val) : "memory"); return; @@ -362,7 +366,7 @@ void __uatomic_add(void *addr, unsigned long val, int len) { __asm__ __volatile__( "lock; addb %1, %0" - : "=m"(*__hp(addr)) + : "=m"(*__hp(len, addr)) : "iq" ((unsigned char)val) : "memory"); return; @@ -371,7 +375,7 @@ void __uatomic_add(void *addr, unsigned long val, int len) { __asm__ __volatile__( "lock; addw %1, %0" - : "=m"(*__hp(addr)) + : "=m"(*__hp(len, addr)) : "ir" ((unsigned short)val) : "memory"); return; @@ -380,7 +384,7 @@ void __uatomic_add(void *addr, unsigned long val, int len) { __asm__ __volatile__( "lock; addl %1, %0" - : "=m"(*__hp(addr)) + : "=m"(*__hp(len, addr)) : "ir" ((unsigned int)val) : "memory"); return; @@ -390,7 +394,7 @@ void __uatomic_add(void *addr, unsigned long val, int len) { __asm__ __volatile__( "lock; addq %1, %0" - : "=m"(*__hp(addr)) + : "=m"(*__hp(len, addr)) : "er" ((unsigned long)val) : "memory"); return; @@ -419,7 +423,7 @@ void __uatomic_inc(void *addr, int len) { __asm__ __volatile__( "lock; incb %0" - : "=m"(*__hp(addr)) + : "=m"(*__hp(len, addr)) : : "memory"); return; @@ -428,7 +432,7 @@ void __uatomic_inc(void *addr, int len) { __asm__ __volatile__( "lock; incw %0" - : "=m"(*__hp(addr)) + : "=m"(*__hp(len, addr)) : : "memory"); return; @@ -437,7 +441,7 @@ void __uatomic_inc(void *addr, int len) { __asm__ __volatile__( "lock; incl %0" - : "=m"(*__hp(addr)) + : "=m"(*__hp(len, addr)) : : "memory"); return; @@ -447,7 +451,7 @@ void __uatomic_inc(void *addr, int len) { __asm__ __volatile__( "lock; incq %0" - : "=m"(*__hp(addr)) + : "=m"(*__hp(len, addr)) : : "memory"); return; @@ -472,7 +476,7 @@ void __uatomic_dec(void *addr, int len) { __asm__ __volatile__( "lock; decb %0" - : "=m"(*__hp(addr)) + : "=m"(*__hp(len, addr)) : : "memory"); return; @@ -481,7 +485,7 @@ void __uatomic_dec(void *addr, int len) { __asm__ __volatile__( "lock; decw %0" - : "=m"(*__hp(addr)) + : "=m"(*__hp(len, addr)) : : "memory"); return; @@ -490,7 +494,7 @@ void __uatomic_dec(void *addr, int len) { __asm__ __volatile__( "lock; decl %0" - : "=m"(*__hp(addr)) + : "=m"(*__hp(len, addr)) : : "memory"); return; @@ -500,7 +504,7 @@ void __uatomic_dec(void *addr, int len) { __asm__ __volatile__( "lock; decq %0" - : "=m"(*__hp(addr)) + : "=m"(*__hp(len, addr)) : : "memory"); return; -- 2.34.1