Ticket #10241: 0001-gcc-libgcc-Implement-atomic-intrinsics.patch

File 0001-gcc-libgcc-Implement-atomic-intrinsics.patch, 14.0 KB (added by zeusk, 10 years ago)

Implement atomic intrinsics in libgcc

  • gcc/libgcc/config.host

    From 1a18f5e660eb57e7f4c4512d184e7bcda54305cb Mon Sep 17 00:00:00 2001
    From: Shantanu Gupta <shans95g@gmail.com>
    Date: Fri, 21 Mar 2014 04:44:45 +0530
    Subject: [PATCH]   gcc/libgcc: Implement atomic intrinsics
    
        Implement atomic intrinsics for ARMv5 and lower
        in libgcc for Haiku.
    
    	modified:   gcc/libgcc/config.host
    	new file:   gcc/libgcc/config/arm/haiku-atomic.c
    	new file:   gcc/libgcc/config/arm/t-haiku-eabi
    ---
     gcc/libgcc/config.host               |   2 +-
     gcc/libgcc/config/arm/haiku-atomic.c | 270 +++++++++++++++++++++++++++++++++++
     gcc/libgcc/config/arm/t-haiku-eabi   |   2 +
     3 files changed, 273 insertions(+), 1 deletion(-)
     create mode 100644 gcc/libgcc/config/arm/haiku-atomic.c
     create mode 100644 gcc/libgcc/config/arm/t-haiku-eabi
    
    diff --git a/gcc/libgcc/config.host b/gcc/libgcc/config.host
    index c835d69..0ff5476 100644
    a b arm*-*-netbsdelf*)  
    323323    tmake_file="$tmake_file arm/t-arm arm/t-netbsd t-slibgcc-gld-nover"
    324324    ;;
    325325arm-*-haiku*)
    326     tmake_file="${tmake_file} arm/t-arm arm/t-elf arm/t-bpabi"
     326    tmake_file="${tmake_file} arm/t-arm arm/t-elf arm/t-bpabi arm/t-haiku-eabi"
    327327    tmake_file="$tmake_file t-softfp-sfdf t-softfp-excl arm/t-softfp t-softfp"
    328328    tm_file="${tm_file} arm/bpabi-lib.h"
    329329    unwind_header=config/arm/unwind-arm.h
  • new file gcc/libgcc/config/arm/haiku-atomic.c

    diff --git a/gcc/libgcc/config/arm/haiku-atomic.c b/gcc/libgcc/config/arm/haiku-atomic.c
    new file mode 100644
    index 0000000..977807d
    - +  
     1/* Haiku-specific atomic operations for libgcc.
     2   Copyright (C) 2008-2013 Free Software Foundation, Inc.
     3   Contributed by CodeSourcery.
     4   Modified for Haiku project by Shantanu Gupta <shans95g@gmail.com> (2014)
     5
     6This file is part of GCC.
     7
     8GCC is free software; you can redistribute it and/or modify it under
     9the terms of the GNU General Public License as published by the Free
     10Software Foundation; either version 3, or (at your option) any later
     11version.
     12
     13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
     14WARRANTY; without even the implied warranty of MERCHANTABILITY or
     15FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     16for more details.
     17
     18Under Section 7 of GPL version 3, you are granted additional
     19permissions described in the GCC Runtime Library Exception, version
     203.1, as published by the Free Software Foundation.
     21
     22You should have received a copy of the GNU General Public License and
     23a copy of the GCC Runtime Library Exception along with this program;
     24see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     25<http://www.gnu.org/licenses/>.  */
     26
     27extern int _kern_atomic_test_and_set(int *value, int newValue, int testAgainst);
     28extern int _kern_atomic_add(int *value, int addValue);
     29extern int _kern_atomic_and(int *value, int andValue);
     30extern int _kern_atomic_or(int *value, int orValue);
     31
     32static inline int _kern_atomic_sub(int *value, int subValue)
     33{
     34    return _kern_atomic_add(value, -subValue);
     35}
     36
     37#define HIDDEN __attribute__ ((visibility ("hidden")))
     38
     39#ifdef __ARMEL__
     40#define INVERT_MASK_1 0
     41#define INVERT_MASK_2 0
     42#else
     43#define INVERT_MASK_1 24
     44#define INVERT_MASK_2 16
     45#endif
     46
     47#define MASK_1 0xffu
     48#define MASK_2 0xffffu
     49
     50#define FETCH_AND_OP_WORD(OP)                  \
     51int HIDDEN                                     \
     52__sync_fetch_and_##OP##_4(int *ptr, int val)   \
     53{                                              \
     54    return _kern_atomic_##OP (ptr, val);       \
     55}
     56
     57// FETCH_AND_OP_WORD (add) TODO: Cleanup duplication in libroot.so
     58FETCH_AND_OP_WORD (sub)
     59FETCH_AND_OP_WORD (or)
     60FETCH_AND_OP_WORD (and)
     61
     62#define FETCH_AND_OP_WORD_EX(OP, PFX_OP, INF_OP)                               \
     63int HIDDEN                                                                     \
     64__sync_fetch_and_##OP##_4(int *ptr, int val)                                   \
     65{                                                                              \
     66    int tmp;                                                                   \
     67                                                                               \
     68    do {                                                                       \
     69        tmp = *ptr;                                                            \
     70    } while(_kern_atomic_test_and_set(ptr, PFX_OP(tmp INF_OP val), tmp) != tmp); \
     71                                                                               \
     72    return tmp;                                                                \
     73}
     74
     75FETCH_AND_OP_WORD_EX (xor,   , ^)  // TODO: Not supported by haiku ?
     76FETCH_AND_OP_WORD_EX (nand, ~, &)  // TODO: Not supported by haiku ?
     77
     78#define OP_AND_FETCH_WORD(OP, INF_OP)                 \
     79int HIDDEN                                            \
     80__sync_##OP##_and_fetch_4(int *ptr, int val)          \
     81{                                                     \
     82    return (_kern_atomic_##OP (ptr, val) INF_OP val); \
     83}
     84
     85OP_AND_FETCH_WORD (add, +)
     86OP_AND_FETCH_WORD (sub, -)
     87OP_AND_FETCH_WORD (or,  |)
     88OP_AND_FETCH_WORD (and, &)
     89
     90#define OP_AND_FETCH_WORD_EX(OP, PFX_OP, INF_OP)                               \
     91int HIDDEN                                                                     \
     92__sync_##OP##_and_fetch_4(int *ptr, int val)                                   \
     93{                                                                              \
     94    int tmp;                                                                   \
     95                                                                               \
     96    do {                                                                       \
     97        tmp = *ptr;                                                            \
     98    } while(_kern_atomic_test_and_set(ptr, PFX_OP(tmp INF_OP val), tmp) != tmp); \
     99                                                                               \
     100    return PFX_OP (tmp INF_OP val);                                            \
     101}
     102
     103OP_AND_FETCH_WORD_EX (xor,   , ^)
     104OP_AND_FETCH_WORD_EX (nand, ~, &)
     105
     106#define NAME_oldval(OP, WIDTH) __sync_fetch_and_##OP##_##WIDTH
     107#define NAME_newval(OP, WIDTH) __sync_##OP##_and_fetch_##WIDTH
     108
     109#define SUBWORD_SYNC_OP(OP, PFX_OP, INF_OP, TYPE, WIDTH, RETURN)               \
     110TYPE HIDDEN                                                                    \
     111NAME##_##RETURN (OP, WIDTH) (TYPE *ptr, TYPE val)                              \
     112{                                                                              \
     113    int *wordptr = (int *) ((unsigned int) ptr & ~3);                          \
     114    unsigned int mask, shift, oldval, newval;                                  \
     115                                                                               \
     116    shift = (((unsigned int) ptr & 3) << 3) ^ INVERT_MASK_##WIDTH;             \
     117    mask = MASK_##WIDTH << shift;                                              \
     118                                                                               \
     119    do {                                                                       \
     120        oldval = *wordptr;                                                     \
     121        newval = ((PFX_OP (((oldval & mask) >> shift)                          \
     122                    INF_OP (unsigned int) val)) << shift) & mask;              \
     123        newval |= oldval & ~mask;                                              \
     124    } while ((unsigned int) _kern_atomic_test_and_set(wordptr, newval, oldval) \
     125                != oldval);                                                    \
     126                                                                               \
     127    return (RETURN & mask) >> shift;                                           \
     128}
     129
     130SUBWORD_SYNC_OP (add,   , +, short, 2, oldval)
     131SUBWORD_SYNC_OP (sub,   , -, short, 2, oldval)
     132SUBWORD_SYNC_OP (or,    , |, short, 2, oldval)
     133SUBWORD_SYNC_OP (and,   , &, short, 2, oldval)
     134SUBWORD_SYNC_OP (xor,   , ^, short, 2, oldval)
     135SUBWORD_SYNC_OP (nand, ~, &, short, 2, oldval)
     136
     137SUBWORD_SYNC_OP (add,   , +, signed char, 1, oldval)
     138SUBWORD_SYNC_OP (sub,   , -, signed char, 1, oldval)
     139SUBWORD_SYNC_OP (or,    , |, signed char, 1, oldval)
     140SUBWORD_SYNC_OP (and,   , &, signed char, 1, oldval)
     141SUBWORD_SYNC_OP (xor,   , ^, signed char, 1, oldval)
     142SUBWORD_SYNC_OP (nand, ~, &, signed char, 1, oldval)
     143
     144SUBWORD_SYNC_OP (add,   , +, short, 2, newval)
     145SUBWORD_SYNC_OP (sub,   , -, short, 2, newval)
     146SUBWORD_SYNC_OP (or,    , |, short, 2, newval)
     147SUBWORD_SYNC_OP (and,   , &, short, 2, newval)
     148SUBWORD_SYNC_OP (xor,   , ^, short, 2, newval)
     149SUBWORD_SYNC_OP (nand, ~, &, short, 2, newval)
     150
     151SUBWORD_SYNC_OP (add,   , +, signed char, 1, newval)
     152SUBWORD_SYNC_OP (sub,   , -, signed char, 1, newval)
     153SUBWORD_SYNC_OP (or,    , |, signed char, 1, newval)
     154SUBWORD_SYNC_OP (and,   , &, signed char, 1, newval)
     155SUBWORD_SYNC_OP (xor,   , ^, signed char, 1, newval)
     156SUBWORD_SYNC_OP (nand, ~, &, signed char, 1, newval)
     157
     158int HIDDEN
     159__sync_val_compare_and_swap_4 (int *ptr, int oldval, int newval)
     160{
     161    int actual_oldval;
     162
     163    for (;;)
     164    {
     165        actual_oldval = *ptr;
     166
     167        if (__builtin_expect (oldval != actual_oldval, 0))
     168            return actual_oldval;
     169
     170        if (_kern_atomic_test_and_set(ptr, newval, oldval) == oldval)
     171            return oldval;
     172    }
     173}
     174
     175#define SUBWORD_VAL_CAS(TYPE, WIDTH)                                           \
     176TYPE HIDDEN                                                                    \
     177__sync_val_compare_and_swap_##WIDTH (TYPE *ptr, TYPE oldval, TYPE newval)      \
     178{                                                                              \
     179    int *wordptr = (int *)((unsigned int) ptr & ~3);                           \
     180    unsigned int mask, shift, actual_oldval, actual_newval;                    \
     181                                                                               \
     182    shift = (((unsigned int) ptr & 3) << 3) ^ INVERT_MASK_##WIDTH;             \
     183    mask = MASK_##WIDTH << shift;                                              \
     184                                                                               \
     185    for (;;)                                                                   \
     186    {                                                                          \
     187        actual_oldval = *wordptr;                                              \
     188                                                                               \
     189        if (__builtin_expect (((actual_oldval & mask) >> shift) !=             \
     190                ((unsigned int) oldval & MASK_##WIDTH), 0))                    \
     191            return (actual_oldval & mask) >> shift;                            \
     192                                                                               \
     193        actual_newval = (actual_oldval & ~mask)                                \
     194                | (((unsigned int) newval << shift) & mask);                   \
     195                                                                               \
     196        if ((unsigned int) _kern_atomic_test_and_set(wordptr, actual_newval,   \
     197                             actual_oldval) == actual_oldval)                  \
     198                 return oldval;                                                \
     199    }                                                                          \
     200}
     201
     202SUBWORD_VAL_CAS (short,       2)
     203SUBWORD_VAL_CAS (signed char, 1)
     204
     205typedef unsigned char bool;
     206
     207bool HIDDEN
     208__sync_bool_compare_and_swap_4 (int *ptr, int oldval, int newval)
     209{
     210    return (_kern_atomic_test_and_set(ptr, newval, oldval) == oldval);
     211}
     212
     213#define SUBWORD_BOOL_CAS(TYPE, WIDTH)                                               \
     214bool HIDDEN                                                                         \
     215__sync_bool_compare_and_swap_##WIDTH (TYPE *ptr, TYPE oldval, TYPE newval)          \
     216{                                                                                   \
     217    TYPE actual_oldval = __sync_val_compare_and_swap_##WIDTH (ptr, oldval, newval); \
     218    return (oldval == actual_oldval);                                               \
     219}
     220
     221SUBWORD_BOOL_CAS (short,       2)
     222SUBWORD_BOOL_CAS (signed char, 1)
     223
     224int HIDDEN
     225__sync_lock_test_and_set_4 (int *ptr, int val)
     226{
     227    int oldval;
     228
     229    do {
     230        oldval = *ptr;
     231    } while(_kern_atomic_test_and_set(ptr, val, oldval) != oldval);
     232
     233    return oldval;
     234}
     235
     236#define SUBWORD_TEST_AND_SET(TYPE, WIDTH)                                      \
     237TYPE HIDDEN                                                                    \
     238__sync_lock_test_and_set_##WIDTH (TYPE *ptr, TYPE val)                         \
     239{                                                                              \
     240    unsigned int oldval, newval, shift, mask;                                  \
     241    int *wordptr = (int *) ((unsigned int) ptr & ~3);                          \
     242                                                                               \
     243    shift = (((unsigned int) ptr & 3) << 3) ^ INVERT_MASK_##WIDTH;             \
     244    mask = MASK_##WIDTH << shift;                                              \
     245                                                                               \
     246    do {                                                                       \
     247        oldval = *wordptr;                                                     \
     248        newval = (oldval & ~mask)                                              \
     249                    | (((unsigned int) val << shift) & mask);                  \
     250    } while ((unsigned int) _kern_atomic_test_and_set(wordptr, newval, oldval) \
     251                != oldval);                                                    \
     252                                                                               \
     253    return (oldval & mask) >> shift;                                           \
     254}
     255
     256SUBWORD_TEST_AND_SET (short,       2)
     257SUBWORD_TEST_AND_SET (signed char, 1)
     258
     259#define SYNC_LOCK_RELEASE(TYPE, WIDTH)   \
     260void HIDDEN                              \
     261__sync_lock_release_##WIDTH (TYPE *ptr)  \
     262{                                        \
     263    *ptr = 0;                            \
     264}
     265
     266SYNC_LOCK_RELEASE (long long,   8)
     267SYNC_LOCK_RELEASE (int,   4)
     268SYNC_LOCK_RELEASE (short, 2)
     269SYNC_LOCK_RELEASE (char,  1)
     270
  • new file gcc/libgcc/config/arm/t-haiku-eabi

    diff --git a/gcc/libgcc/config/arm/t-haiku-eabi b/gcc/libgcc/config/arm/t-haiku-eabi
    new file mode 100644
    index 0000000..f1c0b02
    - +  
     1LIB2ADD_ST += $(srcdir)/config/arm/haiku-atomic.c
     2