From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 96882 invoked by alias); 7 Nov 2016 16:38:41 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Received: (qmail 96860 invoked by uid 89); 7 Nov 2016 16:38:40 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.8 required=5.0 tests=AWL,BAYES_00,KAM_LAZY_DOMAIN_SECURITY autolearn=no version=3.3.2 spammy=sem, H*c:Multipart, advertise, firstly X-HELO: shards.monkeyblade.net Date: Mon, 07 Nov 2016 16:38:00 -0000 Message-Id: <20161107.113825.631166023186879199.davem@davemloft.net> To: carlos@redhat.com Cc: triegel@redhat.com, adhemerval.zanella@linaro.org, andreas@gaisler.com, libc-alpha@sourceware.org, software@gaisler.com Subject: Re: Remove sparcv8 support From: David Miller In-Reply-To: <502720f6-3057-41f5-7832-4b219f5f729f@redhat.com> References: <20161026.144741.1659367414224835783.davem@davemloft.net> <1477565575.7146.199.camel@localhost.localdomain> <502720f6-3057-41f5-7832-4b219f5f729f@redhat.com> Mime-Version: 1.0 Content-Type: Multipart/Mixed; boundary="--Next_Part(Mon_Nov__7_11_38_25_2016_357)--" Content-Transfer-Encoding: 7bit X-SW-Source: 2016-11/txt/msg00243.txt.bz2 ----Next_Part(Mon_Nov__7_11_38_25_2016_357)-- Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit Content-length: 897 So the following attached is what I started playing around with this weekend. It implements software trap "0x23" to perform a CAS operations, the operands are expected in registers %o0, %o1, and %o2. Since it was easiest to test I implemented this first on sparc64 which just executes the CAS instruction directly. I'll start working on the 32-bit part in the background. The capability will be advertised via the mask returned by the "get kernel features" system call. We could check this early in the crt'ish code and cache the value in a variable which the atomics can check. Another kernel side change I have to do is advertise the LEON CAS availability in the _dl_hwcaps so that we can use the LEON CAS in glibc when available. The first patch is the kernel side, and the second is the glibc side. The whole NPTL testsuite passes for the plain 32-bit sparc target with these changes. ----Next_Part(Mon_Nov__7_11_38_25_2016_357)-- Content-Type: Text/X-Patch; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="casemul_kernel.diff" Content-length: 3368 >From fa1cad39df7318cdb46baea5774c340322cd74f2 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 7 Nov 2016 08:27:05 -0800 Subject: [PATCH] sparc64: Add CAS emulation trap. Older 32-bit sparc cpus (other than LEON) lack a CAS instruction, so we need to provide some kind of helper infrastructure in the kernel to emulate it. This is the first part which firstly defines the basic infrastructure and the simplest implementation, which is to just directly execute the instruction on sparc64. We make use of the window fill/spill fault unwind facilities to make this as simple as possible. When we take a full TSB miss, we check if the trap level is greater than one, and if so unwind the trap to one of the final 3 instructions of the interrupted trap handler's block. Which of the three to use is based upon whether this is a real fault, an unaligned access, or a data access exception (ie. bus error). Signed-off-by: David S. Miller --- arch/sparc/include/uapi/asm/unistd.h | 1 + arch/sparc/kernel/Makefile | 1 + arch/sparc/kernel/sys_sparc_64.c | 2 +- arch/sparc/kernel/ttable_64.S | 3 ++- 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/sparc/include/uapi/asm/unistd.h b/arch/sparc/include/uapi/asm/unistd.h index 36eee81..0725911 100644 --- a/arch/sparc/include/uapi/asm/unistd.h +++ b/arch/sparc/include/uapi/asm/unistd.h @@ -430,6 +430,7 @@ /* Bitmask values returned from kern_features system call. */ #define KERN_FEATURE_MIXED_MODE_STACK 0x00000001 +#define KERN_FEATURE_CAS_EMUL 0x00000002 #ifdef __32bit_syscall_numbers__ /* Sparc 32-bit only has the "setresuid32", "getresuid32" variants, diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index fa3c02d..1166638 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -21,6 +21,7 @@ CFLAGS_REMOVE_perf_event.o := -pg CFLAGS_REMOVE_pcr.o := -pg endif +obj-$(CONFIG_SPARC64) += casemul.o obj-$(CONFIG_SPARC64) += urtt_fill.o obj-$(CONFIG_SPARC32) += entry.o wof.o wuf.o obj-$(CONFIG_SPARC32) += etrap_32.o diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index fe8b8ee..d55e8b8 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c @@ -643,5 +643,5 @@ SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act, asmlinkage long sys_kern_features(void) { - return KERN_FEATURE_MIXED_MODE_STACK; + return KERN_FEATURE_MIXED_MODE_STACK | KERN_FEATURE_CAS_EMUL; } diff --git a/arch/sparc/kernel/ttable_64.S b/arch/sparc/kernel/ttable_64.S index c6dfdaa..3364019 100644 --- a/arch/sparc/kernel/ttable_64.S +++ b/arch/sparc/kernel/ttable_64.S @@ -147,7 +147,8 @@ tl0_resv11e: TRAP_UTRAP(UT_TRAP_INSTRUCTION_30,0x11e) TRAP_UTRAP(UT_TRAP_INSTRUC tl0_getcc: GETCC_TRAP tl0_setcc: SETCC_TRAP tl0_getpsr: TRAP(do_getpsr) -tl0_resv123: BTRAP(0x123) BTRAP(0x124) BTRAP(0x125) BTRAP(0x126) BTRAP(0x127) +tl0_cas: TRAP_NOSAVE(emulate_cas) +tl0_resv124: BTRAP(0x124) BTRAP(0x125) BTRAP(0x126) BTRAP(0x127) tl0_resv128: BTRAP(0x128) BTRAP(0x129) BTRAP(0x12a) BTRAP(0x12b) BTRAP(0x12c) tl0_resv12d: BTRAP(0x12d) BTRAP(0x12e) BTRAP(0x12f) BTRAP(0x130) BTRAP(0x131) tl0_resv132: BTRAP(0x132) BTRAP(0x133) BTRAP(0x134) BTRAP(0x135) BTRAP(0x136) -- 2.1.2.532.g19b5d50 ----Next_Part(Mon_Nov__7_11_38_25_2016_357)-- Content-Type: Text/X-Patch; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="casemul_glibc.diff" Content-length: 24470 >From 9e4a9f69dd74c47a7d84c1233164acfae7602a9f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 6 Nov 2016 19:01:31 -0800 Subject: [PATCH] sparc: On 32-bit, provide atomics via kernel assist. Signed-off-by: David S. Miller --- sysdeps/sparc/sparc32/atomic-machine.h | 313 ++------------------- sysdeps/sparc/sparc32/pthread_barrier_wait.c | 1 - sysdeps/sparc/sparc32/sem_post.c | 82 ------ sysdeps/sparc/sparc32/sem_waitcommon.c | 146 ---------- .../sparc/sparc32/sparcv9/pthread_barrier_wait.c | 1 - sysdeps/sparc/sparc32/sparcv9/sem_post.c | 1 - sysdeps/sparc/sparc32/sparcv9/sem_waitcommon.c | 1 - .../unix/sysv/linux/sparc/sparc32/atomic-machine.h | 35 +++ .../linux/sparc/sparc32/sparcv9/atomic-machine.h | 1 + 9 files changed, 55 insertions(+), 526 deletions(-) delete mode 100644 sysdeps/sparc/sparc32/pthread_barrier_wait.c delete mode 100644 sysdeps/sparc/sparc32/sem_post.c delete mode 100644 sysdeps/sparc/sparc32/sem_waitcommon.c delete mode 100644 sysdeps/sparc/sparc32/sparcv9/pthread_barrier_wait.c delete mode 100644 sysdeps/sparc/sparc32/sparcv9/sem_post.c delete mode 100644 sysdeps/sparc/sparc32/sparcv9/sem_waitcommon.c create mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/atomic-machine.h create mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/atomic-machine.h diff --git a/sysdeps/sparc/sparc32/atomic-machine.h b/sysdeps/sparc/sparc32/atomic-machine.h index d6e68f9..ceac729 100644 --- a/sysdeps/sparc/sparc32/atomic-machine.h +++ b/sysdeps/sparc/sparc32/atomic-machine.h @@ -50,311 +50,36 @@ typedef uintmax_t uatomic_max_t; #define __HAVE_64B_ATOMICS 0 #define USE_ATOMIC_COMPILER_BUILTINS 0 +#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \ + (abort (), (__typeof (*mem)) 0) -/* We have no compare and swap, just test and set. - The following implementation contends on 64 global locks - per library and assumes no variable will be accessed using atomic.h - macros from two different libraries. */ +#define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \ + (abort (), (__typeof (*mem)) 0) -__make_section_unallocated - (".gnu.linkonce.b.__sparc32_atomic_locks, \"aw\", %nobits"); +# define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ + __sparc_assisted_compare_and_exchange_val_32_acq ((mem), (newval), (oldval)) -volatile unsigned char __sparc32_atomic_locks[64] - __attribute__ ((nocommon, section (".gnu.linkonce.b.__sparc32_atomic_locks" - __sec_comment), - visibility ("hidden"))); +#define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ + (abort (), (__typeof (*mem)) 0) -#define __sparc32_atomic_do_lock(addr) \ - do \ - { \ - unsigned int __old_lock; \ - unsigned int __idx = (((long) addr >> 2) ^ ((long) addr >> 12)) \ - & 63; \ - do \ - __asm __volatile ("ldstub %1, %0" \ - : "=r" (__old_lock), \ - "=m" (__sparc32_atomic_locks[__idx]) \ - : "m" (__sparc32_atomic_locks[__idx]) \ - : "memory"); \ - while (__old_lock); \ - } \ - while (0) +#define atomic_compare_and_exchange_val_24_acq(mem, newval, oldval) \ + atomic_compare_and_exchange_val_acq (mem, newval, oldval) -#define __sparc32_atomic_do_unlock(addr) \ - do \ - { \ - __sparc32_atomic_locks[(((long) addr >> 2) \ - ^ ((long) addr >> 12)) & 63] = 0; \ - __asm __volatile ("" ::: "memory"); \ - } \ - while (0) - -#define __sparc32_atomic_do_lock24(addr) \ - do \ - { \ - unsigned int __old_lock; \ - do \ - __asm __volatile ("ldstub %1, %0" \ - : "=r" (__old_lock), "=m" (*(addr)) \ - : "m" (*(addr)) \ - : "memory"); \ - while (__old_lock); \ - } \ - while (0) - -#define __sparc32_atomic_do_unlock24(addr) \ - do \ - { \ - __asm __volatile ("" ::: "memory"); \ - *(char *) (addr) = 0; \ - } \ - while (0) - - -#ifndef SHARED -# define __v9_compare_and_exchange_val_32_acq(mem, newval, oldval) \ -({union { __typeof (oldval) a; uint32_t v; } oldval_arg = { .a = (oldval) }; \ - union { __typeof (newval) a; uint32_t v; } newval_arg = { .a = (newval) }; \ - register uint32_t __acev_tmp __asm ("%g6"); \ - register __typeof (mem) __acev_mem __asm ("%g1") = (mem); \ - register uint32_t __acev_oldval __asm ("%g5"); \ - __acev_tmp = newval_arg.v; \ - __acev_oldval = oldval_arg.v; \ - /* .word 0xcde05005 is cas [%g1], %g5, %g6. Can't use cas here though, \ - because as will then mark the object file as V8+ arch. */ \ - __asm __volatile (".word 0xcde05005" \ - : "+r" (__acev_tmp), "=m" (*__acev_mem) \ - : "r" (__acev_oldval), "m" (*__acev_mem), \ - "r" (__acev_mem) : "memory"); \ - (__typeof (oldval)) __acev_tmp; }) -#endif - -/* The only basic operation needed is compare and exchange. */ -#define __v7_compare_and_exchange_val_acq(mem, newval, oldval) \ - ({ __typeof (mem) __acev_memp = (mem); \ - __typeof (*mem) __acev_ret; \ - __typeof (*mem) __acev_newval = (newval); \ - \ - __sparc32_atomic_do_lock (__acev_memp); \ - __acev_ret = *__acev_memp; \ - if (__acev_ret == (oldval)) \ - *__acev_memp = __acev_newval; \ - __sparc32_atomic_do_unlock (__acev_memp); \ - __acev_ret; }) - -#define __v7_compare_and_exchange_bool_acq(mem, newval, oldval) \ - ({ __typeof (mem) __aceb_memp = (mem); \ - int __aceb_ret; \ - __typeof (*mem) __aceb_newval = (newval); \ - \ - __sparc32_atomic_do_lock (__aceb_memp); \ - __aceb_ret = 0; \ - if (*__aceb_memp == (oldval)) \ - *__aceb_memp = __aceb_newval; \ - else \ - __aceb_ret = 1; \ - __sparc32_atomic_do_unlock (__aceb_memp); \ - __aceb_ret; }) - -#define __v7_exchange_acq(mem, newval) \ - ({ __typeof (mem) __acev_memp = (mem); \ - __typeof (*mem) __acev_ret; \ - __typeof (*mem) __acev_newval = (newval); \ - \ - __sparc32_atomic_do_lock (__acev_memp); \ - __acev_ret = *__acev_memp; \ - *__acev_memp = __acev_newval; \ - __sparc32_atomic_do_unlock (__acev_memp); \ - __acev_ret; }) - -#define __v7_exchange_and_add(mem, value) \ - ({ __typeof (mem) __acev_memp = (mem); \ - __typeof (*mem) __acev_ret; \ - \ - __sparc32_atomic_do_lock (__acev_memp); \ - __acev_ret = *__acev_memp; \ - *__acev_memp = __acev_ret + (value); \ - __sparc32_atomic_do_unlock (__acev_memp); \ - __acev_ret; }) - -/* Special versions, which guarantee that top 8 bits of all values - are cleared and use those bits as the ldstub lock. */ -#define __v7_compare_and_exchange_val_24_acq(mem, newval, oldval) \ - ({ __typeof (mem) __acev_memp = (mem); \ - __typeof (*mem) __acev_ret; \ - __typeof (*mem) __acev_newval = (newval); \ - \ - __sparc32_atomic_do_lock24 (__acev_memp); \ - __acev_ret = *__acev_memp & 0xffffff; \ - if (__acev_ret == (oldval)) \ - *__acev_memp = __acev_newval; \ - else \ - __sparc32_atomic_do_unlock24 (__acev_memp); \ - __asm __volatile ("" ::: "memory"); \ - __acev_ret; }) - -#define __v7_exchange_24_rel(mem, newval) \ - ({ __typeof (mem) __acev_memp = (mem); \ - __typeof (*mem) __acev_ret; \ - __typeof (*mem) __acev_newval = (newval); \ - \ - __sparc32_atomic_do_lock24 (__acev_memp); \ - __acev_ret = *__acev_memp & 0xffffff; \ - *__acev_memp = __acev_newval; \ - __asm __volatile ("" ::: "memory"); \ - __acev_ret; }) - -#ifdef SHARED - -/* When dynamically linked, we assume pre-v9 libraries are only ever - used on pre-v9 CPU. */ -# define __atomic_is_v9 0 - -# define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \ - __v7_compare_and_exchange_val_acq (mem, newval, oldval) - -# define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \ - __v7_compare_and_exchange_bool_acq (mem, newval, oldval) - -# define atomic_exchange_acq(mem, newval) \ - __v7_exchange_acq (mem, newval) - -# define atomic_exchange_and_add(mem, value) \ - __v7_exchange_and_add (mem, value) - -# define atomic_compare_and_exchange_val_24_acq(mem, newval, oldval) \ - ({ \ - if (sizeof (*mem) != 4) \ - abort (); \ - __v7_compare_and_exchange_val_24_acq (mem, newval, oldval); }) - -# define atomic_exchange_24_rel(mem, newval) \ - ({ \ - if (sizeof (*mem) != 4) \ - abort (); \ - __v7_exchange_24_rel (mem, newval); }) +#define atomic_exchange_24_rel(mem, newval) \ + atomic_exchange_rel (mem, newval) # define atomic_full_barrier() __asm ("" ::: "memory") # define atomic_read_barrier() atomic_full_barrier () # define atomic_write_barrier() atomic_full_barrier () -#else - -/* In libc.a/libpthread.a etc. we don't know if we'll be run on - pre-v9 or v9 CPU. To be interoperable with dynamically linked - apps on v9 CPUs e.g. with process shared primitives, use cas insn - on v9 CPUs and ldstub on pre-v9. */ - -extern uint64_t _dl_hwcap __attribute__((weak)); -# define __atomic_is_v9 \ - (__builtin_expect (&_dl_hwcap != 0, 1) \ - && __builtin_expect (_dl_hwcap & HWCAP_SPARC_V9, HWCAP_SPARC_V9)) - -# define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \ - ({ \ - __typeof (*mem) __acev_wret; \ - if (sizeof (*mem) != 4) \ - abort (); \ - if (__atomic_is_v9) \ - __acev_wret \ - = __v9_compare_and_exchange_val_32_acq (mem, newval, oldval);\ - else \ - __acev_wret \ - = __v7_compare_and_exchange_val_acq (mem, newval, oldval); \ - __acev_wret; }) - -# define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \ - ({ \ - int __acev_wret; \ - if (sizeof (*mem) != 4) \ - abort (); \ - if (__atomic_is_v9) \ - { \ - __typeof (oldval) __acev_woldval = (oldval); \ - __acev_wret \ - = __v9_compare_and_exchange_val_32_acq (mem, newval, \ - __acev_woldval) \ - != __acev_woldval; \ - } \ - else \ - __acev_wret \ - = __v7_compare_and_exchange_bool_acq (mem, newval, oldval); \ - __acev_wret; }) - -# define atomic_exchange_rel(mem, newval) \ - ({ \ - __typeof (*mem) __acev_wret; \ - if (sizeof (*mem) != 4) \ - abort (); \ - if (__atomic_is_v9) \ - { \ - __typeof (mem) __acev_wmemp = (mem); \ - __typeof (*(mem)) __acev_wval = (newval); \ - do \ - __acev_wret = *__acev_wmemp; \ - while (__builtin_expect \ - (__v9_compare_and_exchange_val_32_acq (__acev_wmemp,\ - __acev_wval, \ - __acev_wret) \ - != __acev_wret, 0)); \ - } \ - else \ - __acev_wret = __v7_exchange_acq (mem, newval); \ - __acev_wret; }) - -# define atomic_compare_and_exchange_val_24_acq(mem, newval, oldval) \ - ({ \ - __typeof (*mem) __acev_wret; \ - if (sizeof (*mem) != 4) \ - abort (); \ - if (__atomic_is_v9) \ - __acev_wret \ - = __v9_compare_and_exchange_val_32_acq (mem, newval, oldval);\ - else \ - __acev_wret \ - = __v7_compare_and_exchange_val_24_acq (mem, newval, oldval);\ - __acev_wret; }) - -# define atomic_exchange_24_rel(mem, newval) \ - ({ \ - __typeof (*mem) __acev_w24ret; \ - if (sizeof (*mem) != 4) \ - abort (); \ - if (__atomic_is_v9) \ - __acev_w24ret = atomic_exchange_rel (mem, newval); \ - else \ - __acev_w24ret = __v7_exchange_24_rel (mem, newval); \ - __acev_w24ret; }) - -#define atomic_full_barrier() \ - do { \ - if (__atomic_is_v9) \ - /* membar #LoadLoad | #LoadStore | #StoreLoad | #StoreStore */ \ - __asm __volatile (".word 0x8143e00f" : : : "memory"); \ - else \ - __asm __volatile ("" : : : "memory"); \ - } while (0) - -#define atomic_read_barrier() \ - do { \ - if (__atomic_is_v9) \ - /* membar #LoadLoad | #LoadStore */ \ - __asm __volatile (".word 0x8143e005" : : : "memory"); \ - else \ - __asm __volatile ("" : : : "memory"); \ - } while (0) - -#define atomic_write_barrier() \ - do { \ - if (__atomic_is_v9) \ - /* membar #LoadStore | #StoreStore */ \ - __asm __volatile (".word 0x8143e00c" : : : "memory"); \ - else \ - __asm __volatile ("" : : : "memory"); \ - } while (0) +void __sparc_link_error (void); +/* An OS-specific atomic-machine.h file will define this macro if + the OS can provide something. If not, we'll fail to build + with a compiler that doesn't supply the operation. */ +#ifndef __sparc_assisted_compare_and_exchange_val_32_acq +# define __sparc_assisted_compare_and_exchange_val_32_acq(mem, newval, oldval) \ + ({ __sparc_link_error (); oldval; }) #endif -#include - #endif /* atomic-machine.h */ diff --git a/sysdeps/sparc/sparc32/pthread_barrier_wait.c b/sysdeps/sparc/sparc32/pthread_barrier_wait.c deleted file mode 100644 index e5ef911..0000000 --- a/sysdeps/sparc/sparc32/pthread_barrier_wait.c +++ /dev/null @@ -1 +0,0 @@ -#error No support for pthread barriers on pre-v9 sparc. diff --git a/sysdeps/sparc/sparc32/sem_post.c b/sysdeps/sparc/sparc32/sem_post.c deleted file mode 100644 index 415a3d5..0000000 --- a/sysdeps/sparc/sparc32/sem_post.c +++ /dev/null @@ -1,82 +0,0 @@ -/* sem_post -- post to a POSIX semaphore. Generic futex-using version. - Copyright (C) 2003-2016 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Jakub Jelinek , 2003. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include -#include -#include -#include -#include -#include -#include - -#include - - -/* See sem_wait for an explanation of the algorithm. */ -int -__new_sem_post (sem_t *sem) -{ - struct new_sem *isem = (struct new_sem *) sem; - int private = isem->private; - unsigned int v; - - __sparc32_atomic_do_lock24 (&isem->pad); - - v = isem->value; - if ((v >> SEM_VALUE_SHIFT) == SEM_VALUE_MAX) - { - __sparc32_atomic_do_unlock24 (&isem->pad); - - __set_errno (EOVERFLOW); - return -1; - } - isem->value = v + (1 << SEM_VALUE_SHIFT); - - __sparc32_atomic_do_unlock24 (&isem->pad); - - if ((v & SEM_NWAITERS_MASK) != 0) - futex_wake (&isem->value, 1, private); - - return 0; -} -versioned_symbol (libpthread, __new_sem_post, sem_post, GLIBC_2_1); - - -#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1) -int -attribute_compat_text_section -__old_sem_post (sem_t *sem) -{ - int *futex = (int *) sem; - - /* We must need to synchronize with consumers of this token, so the atomic - increment must have release MO semantics. */ - atomic_write_barrier (); - (void) atomic_increment_val (futex); - /* We always have to assume it is a shared semaphore. */ - int err = lll_futex_wake (futex, 1, LLL_SHARED); - if (__builtin_expect (err, 0) < 0) - { - __set_errno (-err); - return -1; - } - return 0; -} -compat_symbol (libpthread, __old_sem_post, sem_post, GLIBC_2_0); -#endif diff --git a/sysdeps/sparc/sparc32/sem_waitcommon.c b/sysdeps/sparc/sparc32/sem_waitcommon.c deleted file mode 100644 index 5340f57..0000000 --- a/sysdeps/sparc/sparc32/sem_waitcommon.c +++ /dev/null @@ -1,146 +0,0 @@ -/* sem_waitcommon -- wait on a semaphore, shared code. - Copyright (C) 2003-2016 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Paul Mackerras , 2003. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - - -static void -__sem_wait_32_finish (struct new_sem *sem); - -static void -__sem_wait_cleanup (void *arg) -{ - struct new_sem *sem = (struct new_sem *) arg; - - __sem_wait_32_finish (sem); -} - -/* Wait until at least one token is available, possibly with a timeout. - This is in a separate function in order to make sure gcc - puts the call site into an exception region, and thus the - cleanups get properly run. TODO still necessary? Other futex_wait - users don't seem to need it. */ -static int -__attribute__ ((noinline)) -do_futex_wait (struct new_sem *sem, const struct timespec *abstime) -{ - int err; - - err = futex_abstimed_wait_cancelable (&sem->value, SEM_NWAITERS_MASK, - abstime, sem->private); - - return err; -} - -/* Fast path: Try to grab a token without blocking. */ -static int -__new_sem_wait_fast (struct new_sem *sem, int definitive_result) -{ - unsigned int v; - int ret = 0; - - __sparc32_atomic_do_lock24(&sem->pad); - - v = sem->value; - if ((v >> SEM_VALUE_SHIFT) == 0) - ret = -1; - else - sem->value = v - (1 << SEM_VALUE_SHIFT); - - __sparc32_atomic_do_unlock24(&sem->pad); - - return ret; -} - -/* Slow path that blocks. */ -static int -__attribute__ ((noinline)) -__new_sem_wait_slow (struct new_sem *sem, const struct timespec *abstime) -{ - unsigned int v; - int err = 0; - - __sparc32_atomic_do_lock24(&sem->pad); - - sem->nwaiters++; - - pthread_cleanup_push (__sem_wait_cleanup, sem); - - /* Wait for a token to be available. Retry until we can grab one. */ - v = sem->value; - do - { - if (!(v & SEM_NWAITERS_MASK)) - sem->value = v | SEM_NWAITERS_MASK; - - /* If there is no token, wait. */ - if ((v >> SEM_VALUE_SHIFT) == 0) - { - __sparc32_atomic_do_unlock24(&sem->pad); - - err = do_futex_wait(sem, abstime); - if (err == ETIMEDOUT || err == EINTR) - { - __set_errno (err); - err = -1; - goto error; - } - err = 0; - - __sparc32_atomic_do_lock24(&sem->pad); - - /* We blocked, so there might be a token now. */ - v = sem->value; - } - } - /* If there is no token, we must not try to grab one. */ - while ((v >> SEM_VALUE_SHIFT) == 0); - - sem->value = v - (1 << SEM_VALUE_SHIFT); - - __sparc32_atomic_do_unlock24(&sem->pad); - -error: - pthread_cleanup_pop (0); - - __sem_wait_32_finish (sem); - - return err; -} - -/* Stop being a registered waiter (non-64b-atomics code only). */ -static void -__sem_wait_32_finish (struct new_sem *sem) -{ - __sparc32_atomic_do_lock24(&sem->pad); - - if (--sem->nwaiters == 0) - sem->value &= ~SEM_NWAITERS_MASK; - - __sparc32_atomic_do_unlock24(&sem->pad); -} diff --git a/sysdeps/sparc/sparc32/sparcv9/pthread_barrier_wait.c b/sysdeps/sparc/sparc32/sparcv9/pthread_barrier_wait.c deleted file mode 100644 index 246c8d4..0000000 --- a/sysdeps/sparc/sparc32/sparcv9/pthread_barrier_wait.c +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/sysdeps/sparc/sparc32/sparcv9/sem_post.c b/sysdeps/sparc/sparc32/sparcv9/sem_post.c deleted file mode 100644 index 6a2813c..0000000 --- a/sysdeps/sparc/sparc32/sparcv9/sem_post.c +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/sysdeps/sparc/sparc32/sparcv9/sem_waitcommon.c b/sysdeps/sparc/sparc32/sparcv9/sem_waitcommon.c deleted file mode 100644 index d4a1395..0000000 --- a/sysdeps/sparc/sparc32/sparcv9/sem_waitcommon.c +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/atomic-machine.h b/sysdeps/unix/sysv/linux/sparc/sparc32/atomic-machine.h new file mode 100644 index 0000000..4bb8aa4 --- /dev/null +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/atomic-machine.h @@ -0,0 +1,35 @@ +/* Atomic operations. SPARC/Linux version. + Copyright (C) 2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + . */ + +#include + +#define __sparc_assisted_compare_and_exchange_val_32_acq(mem, newval, oldval)\ +({union { __typeof (oldval) a; uint32_t v; } oldval_arg = { .a = (oldval) }; \ + union { __typeof (newval) a; uint32_t v; } newval_arg = { .a = (newval) }; \ + register uint32_t __acev_tmp __asm ("%o2"); \ + register __typeof (mem) __acev_mem __asm ("%o0") = (mem); \ + register uint32_t __acev_oldval __asm ("%o1"); \ + __acev_tmp = newval_arg.v; \ + __acev_oldval = oldval_arg.v; \ + __asm __volatile ("ta 0x23" \ + : "+r" (__acev_tmp), "=m" (*__acev_mem) \ + : "r" (__acev_oldval), "m" (*__acev_mem), \ + "r" (__acev_mem) : "memory"); \ + (__typeof (oldval)) __acev_tmp; }) + +#include diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/atomic-machine.h b/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/atomic-machine.h new file mode 100644 index 0000000..c5cf630 --- /dev/null +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/atomic-machine.h @@ -0,0 +1 @@ +#include -- 2.1.2.532.g19b5d50 ----Next_Part(Mon_Nov__7_11_38_25_2016_357)----