diff options
author | Michal Meloun <mmel@FreeBSD.org> | 2021-01-02 19:30:00 +0000 |
---|---|---|
committer | Michal Meloun <mmel@FreeBSD.org> | 2021-01-02 19:53:11 +0000 |
commit | bd03acedb804add1e22178d50eb2bfb703974ddf (patch) | |
tree | 88f4079e47ac77042b716163521b1df7ea48250b | |
parent | 80aa931900c863a5d088c49b560488ab32f2d1d9 (diff) | |
download | src-bd03acedb804add1e22178d50eb2bfb703974ddf.tar.gz src-bd03acedb804add1e22178d50eb2bfb703974ddf.zip |
arm: Fix atomic_testand{set,clear}_32(). According to atomic (9), the bit position argument should be a modulo operand size. While I'm in, add missing implementation of atomic_testandclear_64(). For more details see https://reviews.freebsd.org/D27886
Discused with: rlibby
MFC after: 3 weeks
-rw-r--r-- | sys/arm/include/atomic-v6.h | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/sys/arm/include/atomic-v6.h b/sys/arm/include/atomic-v6.h index 38072b5b3d77..ede879cb9fa8 100644 --- a/sys/arm/include/atomic-v6.h +++ b/sys/arm/include/atomic-v6.h @@ -881,7 +881,7 @@ atomic_testandclear_32(volatile uint32_t *ptr, u_int bit) [oldv] "=&r" (oldv), [newv] "=&r" (newv) : [ptr] "r" (ptr), - "[bit]" (bit) + "[bit]" (bit & 0x1f) : "cc", "ip", "memory"); return (result); @@ -902,6 +902,23 @@ atomic_testandclear_long(volatile u_long *p, u_int v) } #define atomic_testandclear_long atomic_testandclear_long + +static __inline int +atomic_testandclear_64(volatile uint64_t *p, u_int v) +{ + volatile uint32_t *p32; + + p32 = (volatile uint32_t *)p; + /* + * Assume little-endian, + * atomic_testandclear_32() uses only last 5 bits of v + */ + if (v >= 32) { + p32++; + } + return (atomic_testandclear_32(p32, v)); +} + static __inline int atomic_testandset_32(volatile uint32_t *ptr, u_int bit) { @@ -925,7 +942,7 @@ atomic_testandset_32(volatile uint32_t *ptr, u_int bit) [oldv] "=&r" (oldv), [newv] "=&r" (newv) : [ptr] "r" (ptr), - "[bit]" (bit) + "[bit]" (bit & 0x1f) : "cc", "ip", "memory"); return (result); @@ -952,9 +969,11 @@ atomic_testandset_64(volatile uint64_t *p, u_int v) volatile uint32_t *p32; p32 = (volatile uint32_t *)p; - /* Assume little-endian */ + /* + * Assume little-endian, + * atomic_testandset_32() uses only last 5 bits of v + */ if (v >= 32) { - v &= 0x1f; p32++; } return (atomic_testandset_32(p32, v)); |