OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [tags/] [gnu-src/] [gcc-4.5.1/] [gcc-4.5.1-or32-1.0rc2/] [gcc/] [config/] [arm/] [linux-atomic.c] - Diff between revs 282 and 384

Only display areas with differences | Details | Blame | View Log

Rev 282 Rev 384
/* Linux-specific atomic operations for ARM EABI.
/* Linux-specific atomic operations for ARM EABI.
   Copyright (C) 2008, 2009 Free Software Foundation, Inc.
   Copyright (C) 2008, 2009 Free Software Foundation, Inc.
   Contributed by CodeSourcery.
   Contributed by CodeSourcery.
 
 
This file is part of GCC.
This file is part of GCC.
 
 
GCC is free software; you can redistribute it and/or modify it under
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
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
Software Foundation; either version 3, or (at your option) any later
version.
version.
 
 
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.
for more details.
 
 
Under Section 7 of GPL version 3, you are granted additional
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
3.1, as published by the Free Software Foundation.
 
 
You should have received a copy of the GNU General Public License and
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;
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
<http://www.gnu.org/licenses/>.  */
<http://www.gnu.org/licenses/>.  */
 
 
/* Kernel helper for compare-and-exchange.  */
/* Kernel helper for compare-and-exchange.  */
typedef int (__kernel_cmpxchg_t) (int oldval, int newval, int *ptr);
typedef int (__kernel_cmpxchg_t) (int oldval, int newval, int *ptr);
#define __kernel_cmpxchg (*(__kernel_cmpxchg_t *) 0xffff0fc0)
#define __kernel_cmpxchg (*(__kernel_cmpxchg_t *) 0xffff0fc0)
 
 
/* Kernel helper for memory barrier.  */
/* Kernel helper for memory barrier.  */
typedef void (__kernel_dmb_t) (void);
typedef void (__kernel_dmb_t) (void);
#define __kernel_dmb (*(__kernel_dmb_t *) 0xffff0fa0)
#define __kernel_dmb (*(__kernel_dmb_t *) 0xffff0fa0)
 
 
/* Note: we implement byte, short and int versions of atomic operations using
/* 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)
   the above kernel helpers, but there is no support for "long long" (64-bit)
   operations as yet.  */
   operations as yet.  */
 
 
#define HIDDEN __attribute__ ((visibility ("hidden")))
#define HIDDEN __attribute__ ((visibility ("hidden")))
 
 
#ifdef __ARMEL__
#ifdef __ARMEL__
#define INVERT_MASK_1 0
#define INVERT_MASK_1 0
#define INVERT_MASK_2 0
#define INVERT_MASK_2 0
#else
#else
#define INVERT_MASK_1 24
#define INVERT_MASK_1 24
#define INVERT_MASK_2 16
#define INVERT_MASK_2 16
#endif
#endif
 
 
#define MASK_1 0xffu
#define MASK_1 0xffu
#define MASK_2 0xffffu
#define MASK_2 0xffffu
 
 
#define FETCH_AND_OP_WORD(OP, PFX_OP, INF_OP)                           \
#define FETCH_AND_OP_WORD(OP, PFX_OP, INF_OP)                           \
  int HIDDEN                                                            \
  int HIDDEN                                                            \
  __sync_fetch_and_##OP##_4 (int *ptr, int val)                         \
  __sync_fetch_and_##OP##_4 (int *ptr, int val)                         \
  {                                                                     \
  {                                                                     \
    int failure, tmp;                                                   \
    int failure, tmp;                                                   \
                                                                        \
                                                                        \
    do {                                                                \
    do {                                                                \
      tmp = *ptr;                                                       \
      tmp = *ptr;                                                       \
      failure = __kernel_cmpxchg (tmp, PFX_OP tmp INF_OP val, ptr);     \
      failure = __kernel_cmpxchg (tmp, PFX_OP tmp INF_OP val, ptr);     \
    } while (failure != 0);                                              \
    } while (failure != 0);                                              \
                                                                        \
                                                                        \
    return tmp;                                                         \
    return tmp;                                                         \
  }
  }
 
 
FETCH_AND_OP_WORD (add,   , +)
FETCH_AND_OP_WORD (add,   , +)
FETCH_AND_OP_WORD (sub,   , -)
FETCH_AND_OP_WORD (sub,   , -)
FETCH_AND_OP_WORD (or,    , |)
FETCH_AND_OP_WORD (or,    , |)
FETCH_AND_OP_WORD (and,   , &)
FETCH_AND_OP_WORD (and,   , &)
FETCH_AND_OP_WORD (xor,   , ^)
FETCH_AND_OP_WORD (xor,   , ^)
FETCH_AND_OP_WORD (nand, ~, &)
FETCH_AND_OP_WORD (nand, ~, &)
 
 
#define NAME_oldval(OP, WIDTH) __sync_fetch_and_##OP##_##WIDTH
#define NAME_oldval(OP, WIDTH) __sync_fetch_and_##OP##_##WIDTH
#define NAME_newval(OP, WIDTH) __sync_##OP##_and_fetch_##WIDTH
#define NAME_newval(OP, WIDTH) __sync_##OP##_and_fetch_##WIDTH
 
 
/* Implement both __sync_<op>_and_fetch and __sync_fetch_and_<op> for
/* Implement both __sync_<op>_and_fetch and __sync_fetch_and_<op> for
   subword-sized quantities.  */
   subword-sized quantities.  */
 
 
#define SUBWORD_SYNC_OP(OP, PFX_OP, INF_OP, TYPE, WIDTH, RETURN)        \
#define SUBWORD_SYNC_OP(OP, PFX_OP, INF_OP, TYPE, WIDTH, RETURN)        \
  TYPE HIDDEN                                                           \
  TYPE HIDDEN                                                           \
  NAME##_##RETURN (OP, WIDTH) (TYPE *ptr, TYPE val)                     \
  NAME##_##RETURN (OP, WIDTH) (TYPE *ptr, TYPE val)                     \
  {                                                                     \
  {                                                                     \
    int *wordptr = (int *) ((unsigned int) ptr & ~3);                   \
    int *wordptr = (int *) ((unsigned int) ptr & ~3);                   \
    unsigned int mask, shift, oldval, newval;                           \
    unsigned int mask, shift, oldval, newval;                           \
    int failure;                                                        \
    int failure;                                                        \
                                                                        \
                                                                        \
    shift = (((unsigned int) ptr & 3) << 3) ^ INVERT_MASK_##WIDTH;      \
    shift = (((unsigned int) ptr & 3) << 3) ^ INVERT_MASK_##WIDTH;      \
    mask = MASK_##WIDTH << shift;                                       \
    mask = MASK_##WIDTH << shift;                                       \
                                                                        \
                                                                        \
    do {                                                                \
    do {                                                                \
      oldval = *wordptr;                                                \
      oldval = *wordptr;                                                \
      newval = ((PFX_OP ((oldval & mask) >> shift)                      \
      newval = ((PFX_OP ((oldval & mask) >> shift)                      \
                 INF_OP (unsigned int) val) << shift) & mask;           \
                 INF_OP (unsigned int) val) << shift) & mask;           \
      newval |= oldval & ~mask;                                         \
      newval |= oldval & ~mask;                                         \
      failure = __kernel_cmpxchg (oldval, newval, wordptr);             \
      failure = __kernel_cmpxchg (oldval, newval, wordptr);             \
    } while (failure != 0);                                              \
    } while (failure != 0);                                              \
                                                                        \
                                                                        \
    return (RETURN & mask) >> shift;                                    \
    return (RETURN & mask) >> shift;                                    \
  }
  }
 
 
SUBWORD_SYNC_OP (add,   , +, short, 2, oldval)
SUBWORD_SYNC_OP (add,   , +, short, 2, oldval)
SUBWORD_SYNC_OP (sub,   , -, short, 2, oldval)
SUBWORD_SYNC_OP (sub,   , -, short, 2, oldval)
SUBWORD_SYNC_OP (or,    , |, short, 2, oldval)
SUBWORD_SYNC_OP (or,    , |, short, 2, oldval)
SUBWORD_SYNC_OP (and,   , &, short, 2, oldval)
SUBWORD_SYNC_OP (and,   , &, short, 2, oldval)
SUBWORD_SYNC_OP (xor,   , ^, short, 2, oldval)
SUBWORD_SYNC_OP (xor,   , ^, short, 2, oldval)
SUBWORD_SYNC_OP (nand, ~, &, short, 2, oldval)
SUBWORD_SYNC_OP (nand, ~, &, short, 2, oldval)
 
 
SUBWORD_SYNC_OP (add,   , +, char, 1, oldval)
SUBWORD_SYNC_OP (add,   , +, char, 1, oldval)
SUBWORD_SYNC_OP (sub,   , -, char, 1, oldval)
SUBWORD_SYNC_OP (sub,   , -, char, 1, oldval)
SUBWORD_SYNC_OP (or,    , |, char, 1, oldval)
SUBWORD_SYNC_OP (or,    , |, char, 1, oldval)
SUBWORD_SYNC_OP (and,   , &, char, 1, oldval)
SUBWORD_SYNC_OP (and,   , &, char, 1, oldval)
SUBWORD_SYNC_OP (xor,   , ^, char, 1, oldval)
SUBWORD_SYNC_OP (xor,   , ^, char, 1, oldval)
SUBWORD_SYNC_OP (nand, ~, &, char, 1, oldval)
SUBWORD_SYNC_OP (nand, ~, &, char, 1, oldval)
 
 
#define OP_AND_FETCH_WORD(OP, PFX_OP, INF_OP)                           \
#define OP_AND_FETCH_WORD(OP, PFX_OP, INF_OP)                           \
  int HIDDEN                                                            \
  int HIDDEN                                                            \
  __sync_##OP##_and_fetch_4 (int *ptr, int val)                         \
  __sync_##OP##_and_fetch_4 (int *ptr, int val)                         \
  {                                                                     \
  {                                                                     \
    int tmp, failure;                                                   \
    int tmp, failure;                                                   \
                                                                        \
                                                                        \
    do {                                                                \
    do {                                                                \
      tmp = *ptr;                                                       \
      tmp = *ptr;                                                       \
      failure = __kernel_cmpxchg (tmp, PFX_OP tmp INF_OP val, ptr);     \
      failure = __kernel_cmpxchg (tmp, PFX_OP tmp INF_OP val, ptr);     \
    } while (failure != 0);                                              \
    } while (failure != 0);                                              \
                                                                        \
                                                                        \
    return PFX_OP tmp INF_OP val;                                       \
    return PFX_OP tmp INF_OP val;                                       \
  }
  }
 
 
OP_AND_FETCH_WORD (add,   , +)
OP_AND_FETCH_WORD (add,   , +)
OP_AND_FETCH_WORD (sub,   , -)
OP_AND_FETCH_WORD (sub,   , -)
OP_AND_FETCH_WORD (or,    , |)
OP_AND_FETCH_WORD (or,    , |)
OP_AND_FETCH_WORD (and,   , &)
OP_AND_FETCH_WORD (and,   , &)
OP_AND_FETCH_WORD (xor,   , ^)
OP_AND_FETCH_WORD (xor,   , ^)
OP_AND_FETCH_WORD (nand, ~, &)
OP_AND_FETCH_WORD (nand, ~, &)
 
 
SUBWORD_SYNC_OP (add,   , +, short, 2, newval)
SUBWORD_SYNC_OP (add,   , +, short, 2, newval)
SUBWORD_SYNC_OP (sub,   , -, short, 2, newval)
SUBWORD_SYNC_OP (sub,   , -, short, 2, newval)
SUBWORD_SYNC_OP (or,    , |, short, 2, newval)
SUBWORD_SYNC_OP (or,    , |, short, 2, newval)
SUBWORD_SYNC_OP (and,   , &, short, 2, newval)
SUBWORD_SYNC_OP (and,   , &, short, 2, newval)
SUBWORD_SYNC_OP (xor,   , ^, short, 2, newval)
SUBWORD_SYNC_OP (xor,   , ^, short, 2, newval)
SUBWORD_SYNC_OP (nand, ~, &, short, 2, newval)
SUBWORD_SYNC_OP (nand, ~, &, short, 2, newval)
 
 
SUBWORD_SYNC_OP (add,   , +, char, 1, newval)
SUBWORD_SYNC_OP (add,   , +, char, 1, newval)
SUBWORD_SYNC_OP (sub,   , -, char, 1, newval)
SUBWORD_SYNC_OP (sub,   , -, char, 1, newval)
SUBWORD_SYNC_OP (or,    , |, char, 1, newval)
SUBWORD_SYNC_OP (or,    , |, char, 1, newval)
SUBWORD_SYNC_OP (and,   , &, char, 1, newval)
SUBWORD_SYNC_OP (and,   , &, char, 1, newval)
SUBWORD_SYNC_OP (xor,   , ^, char, 1, newval)
SUBWORD_SYNC_OP (xor,   , ^, char, 1, newval)
SUBWORD_SYNC_OP (nand, ~, &, char, 1, newval)
SUBWORD_SYNC_OP (nand, ~, &, char, 1, newval)
 
 
int HIDDEN
int HIDDEN
__sync_val_compare_and_swap_4 (int *ptr, int oldval, int newval)
__sync_val_compare_and_swap_4 (int *ptr, int oldval, int newval)
{
{
  int actual_oldval, fail;
  int actual_oldval, fail;
 
 
  while (1)
  while (1)
    {
    {
      actual_oldval = *ptr;
      actual_oldval = *ptr;
 
 
      if (oldval != actual_oldval)
      if (oldval != actual_oldval)
        return actual_oldval;
        return actual_oldval;
 
 
      fail = __kernel_cmpxchg (actual_oldval, newval, ptr);
      fail = __kernel_cmpxchg (actual_oldval, newval, ptr);
 
 
      if (!fail)
      if (!fail)
        return oldval;
        return oldval;
    }
    }
}
}
 
 
#define SUBWORD_VAL_CAS(TYPE, WIDTH)                                    \
#define SUBWORD_VAL_CAS(TYPE, WIDTH)                                    \
  TYPE HIDDEN                                                           \
  TYPE HIDDEN                                                           \
  __sync_val_compare_and_swap_##WIDTH (TYPE *ptr, TYPE oldval,          \
  __sync_val_compare_and_swap_##WIDTH (TYPE *ptr, TYPE oldval,          \
                                       TYPE newval)                     \
                                       TYPE newval)                     \
  {                                                                     \
  {                                                                     \
    int *wordptr = (int *)((unsigned int) ptr & ~3), fail;              \
    int *wordptr = (int *)((unsigned int) ptr & ~3), fail;              \
    unsigned int mask, shift, actual_oldval, actual_newval;             \
    unsigned int mask, shift, actual_oldval, actual_newval;             \
                                                                        \
                                                                        \
    shift = (((unsigned int) ptr & 3) << 3) ^ INVERT_MASK_##WIDTH;      \
    shift = (((unsigned int) ptr & 3) << 3) ^ INVERT_MASK_##WIDTH;      \
    mask = MASK_##WIDTH << shift;                                       \
    mask = MASK_##WIDTH << shift;                                       \
                                                                        \
                                                                        \
    while (1)                                                           \
    while (1)                                                           \
      {                                                                 \
      {                                                                 \
        actual_oldval = *wordptr;                                       \
        actual_oldval = *wordptr;                                       \
                                                                        \
                                                                        \
        if (((actual_oldval & mask) >> shift) != (unsigned int) oldval) \
        if (((actual_oldval & mask) >> shift) != (unsigned int) oldval) \
          return (actual_oldval & mask) >> shift;                       \
          return (actual_oldval & mask) >> shift;                       \
                                                                        \
                                                                        \
        actual_newval = (actual_oldval & ~mask)                         \
        actual_newval = (actual_oldval & ~mask)                         \
                        | (((unsigned int) newval << shift) & mask);    \
                        | (((unsigned int) newval << shift) & mask);    \
                                                                        \
                                                                        \
        fail = __kernel_cmpxchg (actual_oldval, actual_newval,          \
        fail = __kernel_cmpxchg (actual_oldval, actual_newval,          \
                                 wordptr);                              \
                                 wordptr);                              \
                                                                        \
                                                                        \
        if (!fail)                                                      \
        if (!fail)                                                      \
          return oldval;                                                \
          return oldval;                                                \
      }                                                                 \
      }                                                                 \
  }
  }
 
 
SUBWORD_VAL_CAS (short, 2)
SUBWORD_VAL_CAS (short, 2)
SUBWORD_VAL_CAS (char,  1)
SUBWORD_VAL_CAS (char,  1)
 
 
typedef unsigned char bool;
typedef unsigned char bool;
 
 
bool HIDDEN
bool HIDDEN
__sync_bool_compare_and_swap_4 (int *ptr, int oldval, int newval)
__sync_bool_compare_and_swap_4 (int *ptr, int oldval, int newval)
{
{
  int failure = __kernel_cmpxchg (oldval, newval, ptr);
  int failure = __kernel_cmpxchg (oldval, newval, ptr);
  return (failure == 0);
  return (failure == 0);
}
}
 
 
#define SUBWORD_BOOL_CAS(TYPE, WIDTH)                                   \
#define SUBWORD_BOOL_CAS(TYPE, WIDTH)                                   \
  bool HIDDEN                                                           \
  bool HIDDEN                                                           \
  __sync_bool_compare_and_swap_##WIDTH (TYPE *ptr, TYPE oldval,         \
  __sync_bool_compare_and_swap_##WIDTH (TYPE *ptr, TYPE oldval,         \
                                        TYPE newval)                    \
                                        TYPE newval)                    \
  {                                                                     \
  {                                                                     \
    TYPE actual_oldval                                                  \
    TYPE actual_oldval                                                  \
      = __sync_val_compare_and_swap_##WIDTH (ptr, oldval, newval);      \
      = __sync_val_compare_and_swap_##WIDTH (ptr, oldval, newval);      \
    return (oldval == actual_oldval);                                   \
    return (oldval == actual_oldval);                                   \
  }
  }
 
 
SUBWORD_BOOL_CAS (short, 2)
SUBWORD_BOOL_CAS (short, 2)
SUBWORD_BOOL_CAS (char,  1)
SUBWORD_BOOL_CAS (char,  1)
 
 
void HIDDEN
void HIDDEN
__sync_synchronize (void)
__sync_synchronize (void)
{
{
  __kernel_dmb ();
  __kernel_dmb ();
}
}
 
 
int HIDDEN
int HIDDEN
__sync_lock_test_and_set_4 (int *ptr, int val)
__sync_lock_test_and_set_4 (int *ptr, int val)
{
{
  int failure, oldval;
  int failure, oldval;
 
 
  do {
  do {
    oldval = *ptr;
    oldval = *ptr;
    failure = __kernel_cmpxchg (oldval, val, ptr);
    failure = __kernel_cmpxchg (oldval, val, ptr);
  } while (failure != 0);
  } while (failure != 0);
 
 
  return oldval;
  return oldval;
}
}
 
 
#define SUBWORD_TEST_AND_SET(TYPE, WIDTH)                               \
#define SUBWORD_TEST_AND_SET(TYPE, WIDTH)                               \
  TYPE HIDDEN                                                           \
  TYPE HIDDEN                                                           \
  __sync_lock_test_and_set_##WIDTH (TYPE *ptr, TYPE val)                \
  __sync_lock_test_and_set_##WIDTH (TYPE *ptr, TYPE val)                \
  {                                                                     \
  {                                                                     \
    int failure;                                                        \
    int failure;                                                        \
    unsigned int oldval, newval, shift, mask;                           \
    unsigned int oldval, newval, shift, mask;                           \
    int *wordptr = (int *) ((unsigned int) ptr & ~3);                   \
    int *wordptr = (int *) ((unsigned int) ptr & ~3);                   \
                                                                        \
                                                                        \
    shift = (((unsigned int) ptr & 3) << 3) ^ INVERT_MASK_##WIDTH;      \
    shift = (((unsigned int) ptr & 3) << 3) ^ INVERT_MASK_##WIDTH;      \
    mask = MASK_##WIDTH << shift;                                       \
    mask = MASK_##WIDTH << shift;                                       \
                                                                        \
                                                                        \
    do {                                                                \
    do {                                                                \
      oldval = *wordptr;                                                \
      oldval = *wordptr;                                                \
      newval = (oldval & ~mask)                                         \
      newval = (oldval & ~mask)                                         \
               | (((unsigned int) val << shift) & mask);                \
               | (((unsigned int) val << shift) & mask);                \
      failure = __kernel_cmpxchg (oldval, newval, wordptr);             \
      failure = __kernel_cmpxchg (oldval, newval, wordptr);             \
    } while (failure != 0);                                              \
    } while (failure != 0);                                              \
                                                                        \
                                                                        \
    return (oldval & mask) >> shift;                                    \
    return (oldval & mask) >> shift;                                    \
  }
  }
 
 
SUBWORD_TEST_AND_SET (short, 2)
SUBWORD_TEST_AND_SET (short, 2)
SUBWORD_TEST_AND_SET (char,  1)
SUBWORD_TEST_AND_SET (char,  1)
 
 
#define SYNC_LOCK_RELEASE(TYPE, WIDTH)                                  \
#define SYNC_LOCK_RELEASE(TYPE, WIDTH)                                  \
  void HIDDEN                                                           \
  void HIDDEN                                                           \
  __sync_lock_release_##WIDTH (TYPE *ptr)                               \
  __sync_lock_release_##WIDTH (TYPE *ptr)                               \
  {                                                                     \
  {                                                                     \
    /* All writes before this point must be seen before we release      \
    /* All writes before this point must be seen before we release      \
       the lock itself.  */                                             \
       the lock itself.  */                                             \
    __kernel_dmb ();                                                    \
    __kernel_dmb ();                                                    \
    *ptr = 0;                                                            \
    *ptr = 0;                                                            \
  }
  }
 
 
SYNC_LOCK_RELEASE (int,   4)
SYNC_LOCK_RELEASE (int,   4)
SYNC_LOCK_RELEASE (short, 2)
SYNC_LOCK_RELEASE (short, 2)
SYNC_LOCK_RELEASE (char,  1)
SYNC_LOCK_RELEASE (char,  1)
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.