linux-atomic.c (__kernel_cmpxchg): Change argument 1 to volatile void *.

* config/pa/linux-atomic.c (__kernel_cmpxchg): Change argument 1 to
	volatile void *.  Remove trap check.
	(__kernel_cmpxchg2): Likewise.
	(FETCH_AND_OP_2): Adjust operand types.
	(OP_AND_FETCH_2): Likewise.
	(FETCH_AND_OP_WORD): Likewise.
	(OP_AND_FETCH_WORD): Likewise.
	(COMPARE_AND_SWAP_2): Likewise.
	(__sync_val_compare_and_swap_4): Likewise.
	(__sync_bool_compare_and_swap_4): Likewise.
	(SYNC_LOCK_TEST_AND_SET_2): Likewise.
	(__sync_lock_test_and_set_4): Likewise.
	(SYNC_LOCK_RELEASE_1): Likewise.  Use __kernel_cmpxchg2 for release.
	(__sync_lock_release_4): Adjust operand types.  Use __kernel_cmpxchg
	for release.
	(__sync_lock_release_8): Remove.

From-SVN: r278377
This commit is contained in:
John David Anglin 2019-11-17 23:11:52 +00:00
parent b906729f81
commit 632b5e3da7
2 changed files with 125 additions and 96 deletions

View File

@ -1,3 +1,22 @@
2019-11-17 John David Anglin <danglin@gcc.gnu.org>
* config/pa/linux-atomic.c (__kernel_cmpxchg): Change argument 1 to
volatile void *. Remove trap check.
(__kernel_cmpxchg2): Likewise.
(FETCH_AND_OP_2): Adjust operand types.
(OP_AND_FETCH_2): Likewise.
(FETCH_AND_OP_WORD): Likewise.
(OP_AND_FETCH_WORD): Likewise.
(COMPARE_AND_SWAP_2): Likewise.
(__sync_val_compare_and_swap_4): Likewise.
(__sync_bool_compare_and_swap_4): Likewise.
(SYNC_LOCK_TEST_AND_SET_2): Likewise.
(__sync_lock_test_and_set_4): Likewise.
(SYNC_LOCK_RELEASE_1): Likewise. Use __kernel_cmpxchg2 for release.
(__sync_lock_release_4): Adjust operand types. Use __kernel_cmpxchg
for release.
(__sync_lock_release_8): Remove.
2019-11-15 Szabolcs Nagy <szabolcs.nagy@arm.com> 2019-11-15 Szabolcs Nagy <szabolcs.nagy@arm.com>
* config/m68k/linux-unwind.h (struct uw_ucontext): Use sigset_t instead * config/m68k/linux-unwind.h (struct uw_ucontext): Use sigset_t instead

View File

@ -41,7 +41,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
/* Kernel helper for compare-and-exchange a 32-bit value. */ /* Kernel helper for compare-and-exchange a 32-bit value. */
static inline long static inline long
__kernel_cmpxchg (int *mem, int oldval, int newval) __kernel_cmpxchg (volatile void *mem, int oldval, int newval)
{ {
register unsigned long lws_mem asm("r26") = (unsigned long) (mem); register unsigned long lws_mem asm("r26") = (unsigned long) (mem);
register int lws_old asm("r25") = oldval; register int lws_old asm("r25") = oldval;
@ -54,20 +54,18 @@ __kernel_cmpxchg (int *mem, int oldval, int newval)
: "i" (LWS_CAS), "r" (lws_mem), "r" (lws_old), "r" (lws_new) : "i" (LWS_CAS), "r" (lws_mem), "r" (lws_old), "r" (lws_new)
: "r1", "r20", "r22", "r23", "r29", "r31", "memory" : "r1", "r20", "r22", "r23", "r29", "r31", "memory"
); );
if (__builtin_expect (lws_errno == -EFAULT || lws_errno == -ENOSYS, 0))
__builtin_trap ();
/* If the kernel LWS call succeeded (lws_errno == 0), lws_ret contains /* If the kernel LWS call succeeded (lws_errno == 0), lws_ret contains
the old value from memory. If this value is equal to OLDVAL, the the old value from memory. If this value is equal to OLDVAL, the
new value was written to memory. If not, return -EBUSY. */ new value was written to memory. If not, return -EBUSY. */
if (!lws_errno && lws_ret != oldval) if (!lws_errno && lws_ret != oldval)
lws_errno = -EBUSY; return -EBUSY;
return lws_errno; return lws_errno;
} }
static inline long static inline long
__kernel_cmpxchg2 (void *mem, const void *oldval, const void *newval, __kernel_cmpxchg2 (volatile void *mem, const void *oldval, const void *newval,
int val_size) int val_size)
{ {
register unsigned long lws_mem asm("r26") = (unsigned long) (mem); register unsigned long lws_mem asm("r26") = (unsigned long) (mem);
@ -88,9 +86,6 @@ __kernel_cmpxchg2 (void *mem, const void *oldval, const void *newval,
if (__builtin_expect (lws_ret == 0, 1)) if (__builtin_expect (lws_ret == 0, 1))
return 0; return 0;
if (__builtin_expect (lws_errno == -EFAULT || lws_errno == -ENOSYS, 0))
__builtin_trap ();
/* If the kernel LWS call fails with no error, return -EBUSY */ /* If the kernel LWS call fails with no error, return -EBUSY */
if (__builtin_expect (!lws_errno, 0)) if (__builtin_expect (!lws_errno, 0))
return -EBUSY; return -EBUSY;
@ -108,13 +103,13 @@ __kernel_cmpxchg2 (void *mem, const void *oldval, const void *newval,
#define FETCH_AND_OP_2(OP, PFX_OP, INF_OP, TYPE, WIDTH, INDEX) \ #define FETCH_AND_OP_2(OP, PFX_OP, INF_OP, TYPE, WIDTH, INDEX) \
TYPE HIDDEN \ TYPE HIDDEN \
__sync_fetch_and_##OP##_##WIDTH (TYPE *ptr, TYPE val) \ __sync_fetch_and_##OP##_##WIDTH (volatile void *ptr, TYPE val) \
{ \ { \
TYPE tmp, newval; \ TYPE tmp, newval; \
long failure; \ long failure; \
\ \
do { \ do { \
tmp = __atomic_load_n (ptr, __ATOMIC_RELAXED); \ tmp = __atomic_load_n ((volatile TYPE *)ptr, __ATOMIC_RELAXED); \
newval = PFX_OP (tmp INF_OP val); \ newval = PFX_OP (tmp INF_OP val); \
failure = __kernel_cmpxchg2 (ptr, &tmp, &newval, INDEX); \ failure = __kernel_cmpxchg2 (ptr, &tmp, &newval, INDEX); \
} while (failure != 0); \ } while (failure != 0); \
@ -122,36 +117,36 @@ __kernel_cmpxchg2 (void *mem, const void *oldval, const void *newval,
return tmp; \ return tmp; \
} }
FETCH_AND_OP_2 (add, , +, long long, 8, 3) FETCH_AND_OP_2 (add, , +, long long unsigned int, 8, 3)
FETCH_AND_OP_2 (sub, , -, long long, 8, 3) FETCH_AND_OP_2 (sub, , -, long long unsigned int, 8, 3)
FETCH_AND_OP_2 (or, , |, long long, 8, 3) FETCH_AND_OP_2 (or, , |, long long unsigned int, 8, 3)
FETCH_AND_OP_2 (and, , &, long long, 8, 3) FETCH_AND_OP_2 (and, , &, long long unsigned int, 8, 3)
FETCH_AND_OP_2 (xor, , ^, long long, 8, 3) FETCH_AND_OP_2 (xor, , ^, long long unsigned int, 8, 3)
FETCH_AND_OP_2 (nand, ~, &, long long, 8, 3) FETCH_AND_OP_2 (nand, ~, &, long long unsigned int, 8, 3)
FETCH_AND_OP_2 (add, , +, short, 2, 1) FETCH_AND_OP_2 (add, , +, short unsigned int, 2, 1)
FETCH_AND_OP_2 (sub, , -, short, 2, 1) FETCH_AND_OP_2 (sub, , -, short unsigned int, 2, 1)
FETCH_AND_OP_2 (or, , |, short, 2, 1) FETCH_AND_OP_2 (or, , |, short unsigned int, 2, 1)
FETCH_AND_OP_2 (and, , &, short, 2, 1) FETCH_AND_OP_2 (and, , &, short unsigned int, 2, 1)
FETCH_AND_OP_2 (xor, , ^, short, 2, 1) FETCH_AND_OP_2 (xor, , ^, short unsigned int, 2, 1)
FETCH_AND_OP_2 (nand, ~, &, short, 2, 1) FETCH_AND_OP_2 (nand, ~, &, short unsigned int, 2, 1)
FETCH_AND_OP_2 (add, , +, signed char, 1, 0) FETCH_AND_OP_2 (add, , +, unsigned char, 1, 0)
FETCH_AND_OP_2 (sub, , -, signed char, 1, 0) FETCH_AND_OP_2 (sub, , -, unsigned char, 1, 0)
FETCH_AND_OP_2 (or, , |, signed char, 1, 0) FETCH_AND_OP_2 (or, , |, unsigned char, 1, 0)
FETCH_AND_OP_2 (and, , &, signed char, 1, 0) FETCH_AND_OP_2 (and, , &, unsigned char, 1, 0)
FETCH_AND_OP_2 (xor, , ^, signed char, 1, 0) FETCH_AND_OP_2 (xor, , ^, unsigned char, 1, 0)
FETCH_AND_OP_2 (nand, ~, &, signed char, 1, 0) FETCH_AND_OP_2 (nand, ~, &, unsigned char, 1, 0)
#define OP_AND_FETCH_2(OP, PFX_OP, INF_OP, TYPE, WIDTH, INDEX) \ #define OP_AND_FETCH_2(OP, PFX_OP, INF_OP, TYPE, WIDTH, INDEX) \
TYPE HIDDEN \ TYPE HIDDEN \
__sync_##OP##_and_fetch_##WIDTH (TYPE *ptr, TYPE val) \ __sync_##OP##_and_fetch_##WIDTH (volatile void *ptr, TYPE val) \
{ \ { \
TYPE tmp, newval; \ TYPE tmp, newval; \
long failure; \ long failure; \
\ \
do { \ do { \
tmp = __atomic_load_n (ptr, __ATOMIC_RELAXED); \ tmp = __atomic_load_n ((volatile TYPE *)ptr, __ATOMIC_RELAXED); \
newval = PFX_OP (tmp INF_OP val); \ newval = PFX_OP (tmp INF_OP val); \
failure = __kernel_cmpxchg2 (ptr, &tmp, &newval, INDEX); \ failure = __kernel_cmpxchg2 (ptr, &tmp, &newval, INDEX); \
} while (failure != 0); \ } while (failure != 0); \
@ -159,36 +154,37 @@ FETCH_AND_OP_2 (nand, ~, &, signed char, 1, 0)
return PFX_OP (tmp INF_OP val); \ return PFX_OP (tmp INF_OP val); \
} }
OP_AND_FETCH_2 (add, , +, long long, 8, 3) OP_AND_FETCH_2 (add, , +, long long unsigned int, 8, 3)
OP_AND_FETCH_2 (sub, , -, long long, 8, 3) OP_AND_FETCH_2 (sub, , -, long long unsigned int, 8, 3)
OP_AND_FETCH_2 (or, , |, long long, 8, 3) OP_AND_FETCH_2 (or, , |, long long unsigned int, 8, 3)
OP_AND_FETCH_2 (and, , &, long long, 8, 3) OP_AND_FETCH_2 (and, , &, long long unsigned int, 8, 3)
OP_AND_FETCH_2 (xor, , ^, long long, 8, 3) OP_AND_FETCH_2 (xor, , ^, long long unsigned int, 8, 3)
OP_AND_FETCH_2 (nand, ~, &, long long, 8, 3) OP_AND_FETCH_2 (nand, ~, &, long long unsigned int, 8, 3)
OP_AND_FETCH_2 (add, , +, short, 2, 1) OP_AND_FETCH_2 (add, , +, short unsigned int, 2, 1)
OP_AND_FETCH_2 (sub, , -, short, 2, 1) OP_AND_FETCH_2 (sub, , -, short unsigned int, 2, 1)
OP_AND_FETCH_2 (or, , |, short, 2, 1) OP_AND_FETCH_2 (or, , |, short unsigned int, 2, 1)
OP_AND_FETCH_2 (and, , &, short, 2, 1) OP_AND_FETCH_2 (and, , &, short unsigned int, 2, 1)
OP_AND_FETCH_2 (xor, , ^, short, 2, 1) OP_AND_FETCH_2 (xor, , ^, short unsigned int, 2, 1)
OP_AND_FETCH_2 (nand, ~, &, short, 2, 1) OP_AND_FETCH_2 (nand, ~, &, short unsigned int, 2, 1)
OP_AND_FETCH_2 (add, , +, signed char, 1, 0) OP_AND_FETCH_2 (add, , +, unsigned char, 1, 0)
OP_AND_FETCH_2 (sub, , -, signed char, 1, 0) OP_AND_FETCH_2 (sub, , -, unsigned char, 1, 0)
OP_AND_FETCH_2 (or, , |, signed char, 1, 0) OP_AND_FETCH_2 (or, , |, unsigned char, 1, 0)
OP_AND_FETCH_2 (and, , &, signed char, 1, 0) OP_AND_FETCH_2 (and, , &, unsigned char, 1, 0)
OP_AND_FETCH_2 (xor, , ^, signed char, 1, 0) OP_AND_FETCH_2 (xor, , ^, unsigned char, 1, 0)
OP_AND_FETCH_2 (nand, ~, &, signed char, 1, 0) OP_AND_FETCH_2 (nand, ~, &, unsigned char, 1, 0)
#define FETCH_AND_OP_WORD(OP, PFX_OP, INF_OP) \ #define FETCH_AND_OP_WORD(OP, PFX_OP, INF_OP) \
int HIDDEN \ unsigned int HIDDEN \
__sync_fetch_and_##OP##_4 (int *ptr, int val) \ __sync_fetch_and_##OP##_4 (volatile void *ptr, unsigned int val) \
{ \ { \
int tmp; \ unsigned int tmp; \
long failure; \ long failure; \
\ \
do { \ do { \
tmp = __atomic_load_n (ptr, __ATOMIC_RELAXED); \ tmp = __atomic_load_n ((volatile unsigned int *)ptr, \
__ATOMIC_RELAXED); \
failure = __kernel_cmpxchg (ptr, tmp, PFX_OP (tmp INF_OP val)); \ failure = __kernel_cmpxchg (ptr, tmp, PFX_OP (tmp INF_OP val)); \
} while (failure != 0); \ } while (failure != 0); \
\ \
@ -203,14 +199,15 @@ FETCH_AND_OP_WORD (xor, , ^)
FETCH_AND_OP_WORD (nand, ~, &) FETCH_AND_OP_WORD (nand, ~, &)
#define OP_AND_FETCH_WORD(OP, PFX_OP, INF_OP) \ #define OP_AND_FETCH_WORD(OP, PFX_OP, INF_OP) \
int HIDDEN \ unsigned int HIDDEN \
__sync_##OP##_and_fetch_4 (int *ptr, int val) \ __sync_##OP##_and_fetch_4 (volatile void *ptr, unsigned int val) \
{ \ { \
int tmp; \ unsigned int tmp; \
long failure; \ long failure; \
\ \
do { \ do { \
tmp = __atomic_load_n (ptr, __ATOMIC_RELAXED); \ tmp = __atomic_load_n ((volatile unsigned int *)ptr, \
__ATOMIC_RELAXED); \
failure = __kernel_cmpxchg (ptr, tmp, PFX_OP (tmp INF_OP val)); \ failure = __kernel_cmpxchg (ptr, tmp, PFX_OP (tmp INF_OP val)); \
} while (failure != 0); \ } while (failure != 0); \
\ \
@ -228,7 +225,7 @@ typedef unsigned char bool;
#define COMPARE_AND_SWAP_2(TYPE, WIDTH, INDEX) \ #define COMPARE_AND_SWAP_2(TYPE, WIDTH, INDEX) \
TYPE HIDDEN \ TYPE HIDDEN \
__sync_val_compare_and_swap_##WIDTH (TYPE *ptr, TYPE oldval, \ __sync_val_compare_and_swap_##WIDTH (volatile void *ptr, TYPE oldval, \
TYPE newval) \ TYPE newval) \
{ \ { \
TYPE actual_oldval; \ TYPE actual_oldval; \
@ -236,7 +233,8 @@ typedef unsigned char bool;
\ \
while (1) \ while (1) \
{ \ { \
actual_oldval = __atomic_load_n (ptr, __ATOMIC_RELAXED); \ actual_oldval = __atomic_load_n ((volatile TYPE *)ptr, \
__ATOMIC_RELAXED); \
\ \
if (__builtin_expect (oldval != actual_oldval, 0)) \ if (__builtin_expect (oldval != actual_oldval, 0)) \
return actual_oldval; \ return actual_oldval; \
@ -248,27 +246,29 @@ typedef unsigned char bool;
} \ } \
} \ } \
\ \
bool HIDDEN \ _Bool HIDDEN \
__sync_bool_compare_and_swap_##WIDTH (TYPE *ptr, TYPE oldval, \ __sync_bool_compare_and_swap_##WIDTH (volatile void *ptr, \
TYPE newval) \ TYPE oldval, TYPE newval) \
{ \ { \
long failure = __kernel_cmpxchg2 (ptr, &oldval, &newval, INDEX); \ long failure = __kernel_cmpxchg2 (ptr, &oldval, &newval, INDEX); \
return (failure == 0); \ return (failure == 0); \
} }
COMPARE_AND_SWAP_2 (long long, 8, 3) COMPARE_AND_SWAP_2 (long long unsigned int, 8, 3)
COMPARE_AND_SWAP_2 (short, 2, 1) COMPARE_AND_SWAP_2 (short unsigned int, 2, 1)
COMPARE_AND_SWAP_2 (char, 1, 0) COMPARE_AND_SWAP_2 (unsigned char, 1, 0)
int HIDDEN unsigned int HIDDEN
__sync_val_compare_and_swap_4 (int *ptr, int oldval, int newval) __sync_val_compare_and_swap_4 (volatile void *ptr, unsigned int oldval,
unsigned int newval)
{ {
long fail; long fail;
int actual_oldval; unsigned int actual_oldval;
while (1) while (1)
{ {
actual_oldval = __atomic_load_n (ptr, __ATOMIC_RELAXED); actual_oldval = __atomic_load_n ((volatile unsigned int *)ptr,
__ATOMIC_RELAXED);
if (__builtin_expect (oldval != actual_oldval, 0)) if (__builtin_expect (oldval != actual_oldval, 0))
return actual_oldval; return actual_oldval;
@ -280,8 +280,9 @@ __sync_val_compare_and_swap_4 (int *ptr, int oldval, int newval)
} }
} }
bool HIDDEN _Bool HIDDEN
__sync_bool_compare_and_swap_4 (int *ptr, int oldval, int newval) __sync_bool_compare_and_swap_4 (volatile void *ptr, unsigned int oldval,
unsigned int newval)
{ {
long failure = __kernel_cmpxchg (ptr, oldval, newval); long failure = __kernel_cmpxchg (ptr, oldval, newval);
return (failure == 0); return (failure == 0);
@ -289,55 +290,64 @@ __sync_bool_compare_and_swap_4 (int *ptr, int oldval, int newval)
#define SYNC_LOCK_TEST_AND_SET_2(TYPE, WIDTH, INDEX) \ #define SYNC_LOCK_TEST_AND_SET_2(TYPE, WIDTH, INDEX) \
TYPE HIDDEN \ TYPE HIDDEN \
__sync_lock_test_and_set_##WIDTH (TYPE *ptr, TYPE val) \ __sync_lock_test_and_set_##WIDTH (volatile void *ptr, TYPE val) \
{ \ { \
TYPE oldval; \ TYPE oldval; \
long failure; \ long failure; \
\ \
do { \ do { \
oldval = __atomic_load_n (ptr, __ATOMIC_RELAXED); \ oldval = __atomic_load_n ((volatile TYPE *)ptr, \
__ATOMIC_RELAXED); \
failure = __kernel_cmpxchg2 (ptr, &oldval, &val, INDEX); \ failure = __kernel_cmpxchg2 (ptr, &oldval, &val, INDEX); \
} while (failure != 0); \ } while (failure != 0); \
\ \
return oldval; \ return oldval; \
} }
SYNC_LOCK_TEST_AND_SET_2 (long long, 8, 3) SYNC_LOCK_TEST_AND_SET_2 (long long unsigned int, 8, 3)
SYNC_LOCK_TEST_AND_SET_2 (short, 2, 1) SYNC_LOCK_TEST_AND_SET_2 (short unsigned int, 2, 1)
SYNC_LOCK_TEST_AND_SET_2 (signed char, 1, 0) SYNC_LOCK_TEST_AND_SET_2 (unsigned char, 1, 0)
int HIDDEN unsigned int HIDDEN
__sync_lock_test_and_set_4 (int *ptr, int val) __sync_lock_test_and_set_4 (volatile void *ptr, unsigned int val)
{ {
long failure; long failure;
int oldval; unsigned int oldval;
do { do {
oldval = __atomic_load_n (ptr, __ATOMIC_RELAXED); oldval = __atomic_load_n ((volatile unsigned int *)ptr, __ATOMIC_RELAXED);
failure = __kernel_cmpxchg (ptr, oldval, val); failure = __kernel_cmpxchg (ptr, oldval, val);
} while (failure != 0); } while (failure != 0);
return oldval; return oldval;
} }
void HIDDEN #define SYNC_LOCK_RELEASE_1(TYPE, WIDTH, INDEX) \
__sync_lock_release_8 (long long *ptr)
{
/* All accesses must be complete before we release the lock. */
__sync_synchronize ();
*(double *)ptr = 0;
}
#define SYNC_LOCK_RELEASE_1(TYPE, WIDTH) \
void HIDDEN \ void HIDDEN \
__sync_lock_release_##WIDTH (TYPE *ptr) \ __sync_lock_release_##WIDTH (volatile void *ptr) \
{ \ { \
/* All accesses must be complete before we release \ TYPE oldval, val = 0; \
the lock. */ \ long failure; \
__sync_synchronize (); \ \
*ptr = 0; \ do { \
oldval = __atomic_load_n ((volatile TYPE *)ptr, \
__ATOMIC_RELAXED); \
failure = __kernel_cmpxchg2 (ptr, &oldval, &val, INDEX); \
} while (failure != 0); \
} }
SYNC_LOCK_RELEASE_1 (int, 4) SYNC_LOCK_RELEASE_1 (long long unsigned int, 8, 3)
SYNC_LOCK_RELEASE_1 (short, 2) SYNC_LOCK_RELEASE_1 (short unsigned int, 2, 1)
SYNC_LOCK_RELEASE_1 (signed char, 1) SYNC_LOCK_RELEASE_1 (unsigned char, 1, 0)
void HIDDEN
__sync_lock_release_4 (volatile void *ptr)
{
long failure;
unsigned int oldval;
do {
oldval = __atomic_load_n ((volatile unsigned int *)ptr, __ATOMIC_RELAXED);
failure = __kernel_cmpxchg (ptr, oldval, 0);
} while (failure != 0);
}