From patchwork Tue Jul 26 09:01:16 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Dr. David Alan Gilbert" X-Patchwork-Id: 3125 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id BFF6D23F41 for ; Tue, 26 Jul 2011 09:01:22 +0000 (UTC) Received: from mail-qw0-f52.google.com (mail-qw0-f52.google.com [209.85.216.52]) by fiordland.canonical.com (Postfix) with ESMTP id 7DAE9A186B8 for ; Tue, 26 Jul 2011 09:01:22 +0000 (UTC) Received: by qwb8 with SMTP id 8so136841qwb.11 for ; Tue, 26 Jul 2011 02:01:22 -0700 (PDT) Received: by 10.229.1.217 with SMTP id 25mr1809535qcg.38.1311670882011; Tue, 26 Jul 2011 02:01:22 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.229.217.78 with SMTP id hl14cs103949qcb; Tue, 26 Jul 2011 02:01:21 -0700 (PDT) Received: by 10.216.8.200 with SMTP id 50mr1414168wer.37.1311670880612; Tue, 26 Jul 2011 02:01:20 -0700 (PDT) Received: from lon1-post-2.mail.demon.net (lon1-post-2.mail.demon.net [195.173.77.149]) by mx.google.com with ESMTP id k5si493408wed.84.2011.07.26.02.01.20; Tue, 26 Jul 2011 02:01:20 -0700 (PDT) Received-SPF: neutral (google.com: 195.173.77.149 is neither permitted nor denied by best guess record for domain of david.gilbert@linaro.org) client-ip=195.173.77.149; Authentication-Results: mx.google.com; spf=neutral (google.com: 195.173.77.149 is neither permitted nor denied by best guess record for domain of david.gilbert@linaro.org) smtp.mail=david.gilbert@linaro.org Received: from tu006.demon.co.uk ([83.105.84.125] helo=gort.home.treblig.org) by lon1-post-2.mail.demon.net with esmtp (Exim 4.69) id 1QldVv-0006rQ-cE; Tue, 26 Jul 2011 09:01:19 +0000 Received: from [192.168.66.106] (helo=davesworkthinkpad) by gort.home.treblig.org with esmtp (Exim 4.72) (envelope-from ) id 1QldVs-0001BD-Gs; Tue, 26 Jul 2011 10:01:16 +0100 Date: Tue, 26 Jul 2011 10:01:16 +0100 From: "Dr. David Alan Gilbert" To: gcc-patches@gcc.gnu.org Cc: ramana.radhakrishnan@linaro.org, rth@redhat.com, joseph@codesourcery.com, patches@linaro.org Subject: [Patch 2/4] ARM 64 bit sync atomic operations [V2] Message-ID: <20110726090115.GC6925@davesworkthinkpad> References: <20110701155254.GA5242@davesworkthinkpad> <20110726085910.GA6925@davesworkthinkpad> <20110726090039.GB6925@davesworkthinkpad> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20110726090039.GB6925@davesworkthinkpad> User-Agent: Mutt/1.5.20 (2009-06-14) Add ARM 64bit sync helpers for use on older ARMs. Based on 32bit versions but with check for sufficiently new kernel version. gcc/ * config/arm/linux-atomic-64bit.c: New (based on linux-atomic.c) * config/arm/linux-atomic.c: Change comment to point to 64bit version (SYNC_LOCK_RELEASE): Instantiate 64bit version. * config/arm/t-linux-eabi: Pull in linux-atomic-64bit.c diff --git a/gcc/config/arm/linux-atomic-64bit.c b/gcc/config/arm/linux-atomic-64bit.c new file mode 100644 index 0000000..8b65de8 --- /dev/null +++ b/gcc/config/arm/linux-atomic-64bit.c @@ -0,0 +1,162 @@ +/* 64bit Linux-specific atomic operations for ARM EABI. + Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Based on linux-atomic.c + + 64 bit additions david.gilbert@linaro.org + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC 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 General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +/* 64bit helper functions for atomic operations; the compiler will + call these when the code is compiled for a CPU without ldrexd/strexd. + (If the CPU had those then the compiler inlines the operation). + + These helpers require a kernel helper that's only present on newer + kernels; we check for that in an init section and bail out rather + unceremoneously. */ + +extern unsigned int __write(int fd, const void *buf, unsigned int count); +extern void abort(void); + +/* Kernel helper for compare-and-exchange. */ +typedef int (__kernel_cmpxchg64_t) (const long long* oldval, + const long long* newval, + long long *ptr); +#define __kernel_cmpxchg64 (*(__kernel_cmpxchg64_t *) 0xffff0f60) + +/* Kernel helper page version number */ +#define __kernel_helper_version (*(unsigned int *)0xffff0ffc) + +/* Check that the kernel has a new enough version at load */ +static void __check_for_sync8_kernelhelper (void) +{ + if (__kernel_helper_version < 5) + { + const char err[] = "A newer kernel is required to run this binary. (__kernel_cmpxchg64 helper)\n"; + /* At this point we need a way to crash with some information + for the user - I'm not sure I can rely on much else being + available at this point, so do the same as generic-morestack.c + write() and abort(). */ + __write (2 /* stderr */, err, sizeof(err)); + abort (); + } +}; + +static void (*__sync8_kernelhelper_inithook[]) (void) __attribute__ ((used, section (".init_array"))) = { + &__check_for_sync8_kernelhelper +}; + +#define HIDDEN __attribute__ ((visibility ("hidden"))) + +#define FETCH_AND_OP_WORD64(OP, PFX_OP, INF_OP) \ + long long HIDDEN \ + __sync_fetch_and_##OP##_8 (long long *ptr, long long val) \ + { \ + int failure; \ + long long tmp,tmp2; \ + \ + do { \ + tmp = *ptr; \ + tmp2 = PFX_OP (tmp INF_OP val); \ + failure = __kernel_cmpxchg64 (&tmp, &tmp2, ptr); \ + } while (failure != 0); \ + \ + return tmp; \ + } + +FETCH_AND_OP_WORD64 (add, , +) +FETCH_AND_OP_WORD64 (sub, , -) +FETCH_AND_OP_WORD64 (or, , |) +FETCH_AND_OP_WORD64 (and, , &) +FETCH_AND_OP_WORD64 (xor, , ^) +FETCH_AND_OP_WORD64 (nand, ~, &) + +#define NAME_oldval(OP, WIDTH) __sync_fetch_and_##OP##_##WIDTH +#define NAME_newval(OP, WIDTH) __sync_##OP##_and_fetch_##WIDTH + +/* Implement both __sync__and_fetch and __sync_fetch_and_ for + subword-sized quantities. */ + +#define OP_AND_FETCH_WORD64(OP, PFX_OP, INF_OP) \ + long long HIDDEN \ + __sync_##OP##_and_fetch_8 (long long *ptr, long long val) \ + { \ + int failure; \ + long long tmp,tmp2; \ + \ + do { \ + tmp = *ptr; \ + tmp2 = PFX_OP (tmp INF_OP val); \ + failure = __kernel_cmpxchg64 (&tmp, &tmp2, ptr); \ + } while (failure != 0); \ + \ + return tmp2; \ + } + +OP_AND_FETCH_WORD64 (add, , +) +OP_AND_FETCH_WORD64 (sub, , -) +OP_AND_FETCH_WORD64 (or, , |) +OP_AND_FETCH_WORD64 (and, , &) +OP_AND_FETCH_WORD64 (xor, , ^) +OP_AND_FETCH_WORD64 (nand, ~, &) + +long long HIDDEN +__sync_val_compare_and_swap_8 (long long *ptr, long long oldval, long long newval) +{ + int failure; + long long actual_oldval; + + while (1) + { + actual_oldval = *ptr; + + if (__builtin_expect (oldval != actual_oldval, 0)) + return actual_oldval; + + failure = __kernel_cmpxchg64 (&actual_oldval, &newval, ptr); + + if (__builtin_expect (!failure, 1)) + return oldval; + } +} + +typedef unsigned char bool; + +bool HIDDEN +__sync_bool_compare_and_swap_8 (long long *ptr, long long oldval, long long newval) +{ + int failure = __kernel_cmpxchg64 (&oldval, &newval, ptr); + return (failure == 0); +} + +long long HIDDEN +__sync_lock_test_and_set_8 (long long *ptr, long long val) +{ + int failure; + long long oldval; + + do { + oldval = *ptr; + failure = __kernel_cmpxchg64 (&oldval, &val, ptr); + } while (failure != 0); + + return oldval; +} diff --git a/gcc/config/arm/linux-atomic.c b/gcc/config/arm/linux-atomic.c index 57065a6..80f161d 100644 --- a/gcc/config/arm/linux-atomic.c +++ b/gcc/config/arm/linux-atomic.c @@ -32,8 +32,8 @@ typedef void (__kernel_dmb_t) (void); #define __kernel_dmb (*(__kernel_dmb_t *) 0xffff0fa0) /* Note: we implement byte, short and int versions of atomic operations using - the above kernel helpers, but there is no support for "long long" (64-bit) - operations as yet. */ + the above kernel helpers; see linux-atomic-64bit.c for "long long" (64-bit) + operations. */ #define HIDDEN __attribute__ ((visibility ("hidden"))) @@ -273,6 +273,7 @@ SUBWORD_TEST_AND_SET (unsigned char, 1) *ptr = 0; \ } +SYNC_LOCK_RELEASE (long long, 8) SYNC_LOCK_RELEASE (int, 4) SYNC_LOCK_RELEASE (short, 2) SYNC_LOCK_RELEASE (char, 1) diff --git a/gcc/config/arm/t-linux-eabi b/gcc/config/arm/t-linux-eabi index a328a00..3814cc0 100644 --- a/gcc/config/arm/t-linux-eabi +++ b/gcc/config/arm/t-linux-eabi @@ -36,3 +36,4 @@ LIB1ASMFUNCS := $(filter-out _dvmd_tls,$(LIB1ASMFUNCS)) _dvmd_lnx _clear_cache EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o LIB2FUNCS_STATIC_EXTRA += $(srcdir)/config/arm/linux-atomic.c +LIB2FUNCS_STATIC_EXTRA += $(srcdir)/config/arm/linux-atomic-64bit.c