From patchwork Mon Nov 7 16:38:25 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Miller X-Patchwork-Id: 81124 Delivered-To: patch@linaro.org Received: by 10.140.97.165 with SMTP id m34csp1103032qge; Mon, 7 Nov 2016 08:38:53 -0800 (PST) X-Received: by 10.98.137.153 with SMTP id n25mr14905619pfk.89.1478536733570; Mon, 07 Nov 2016 08:38:53 -0800 (PST) Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id ww9si26820596pab.171.2016.11.07.08.38.53 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 07 Nov 2016 08:38:53 -0800 (PST) Received-SPF: pass (google.com: domain of libc-alpha-return-74490-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@sourceware.org; spf=pass (google.com: domain of libc-alpha-return-74490-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=libc-alpha-return-74490-patch=linaro.org@sourceware.org DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:date:message-id:to:cc:subject:from:in-reply-to :references:mime-version:content-type:content-transfer-encoding; q=dns; s=default; b=ui/da6U4nu4wWV/YDwmOvYUVJH6z92+7nJ6MF7xWYJi e6IOzrEWRfLYk7tCqNah42QsKsPoOSgBKb5IOgTWkyxo36TcQ1OIS4Jb4XMmRtsk 8uBe/xgGitSAG2KmzAljiGsFoY0iSW3ojhrUrGaW95rrGmWUJ7YvcWKXJIq67/zE = DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:date:message-id:to:cc:subject:from:in-reply-to :references:mime-version:content-type:content-transfer-encoding; s=default; bh=28ijzoyEHFTNQtVSnNn9w3RJbjI=; b=cv59xeXzom5wkAHnY nx1IqF8kwMV8oFMmXP9aQ4vaJ3LcUN76BOImBpWOhqKDJ7FWUCKR12PZnJjoFhE7 ZHhgeZC04maWYQ7Pp7KlNkUcGF89GSKZrFCTXGa8C+YRVfnCmgx0TuOFfKfwhAYK S+h2EG1A+OJvz/L+rXAsMk8GCU= 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-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@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 11:38:25 -0500 (EST) 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 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. >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