Back to index

glibc  2.9
atomic.h
Go to the documentation of this file.
00001 /* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003 
00004    The GNU C Library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Lesser General Public
00006    License as published by the Free Software Foundation; either
00007    version 2.1 of the License, or (at your option) any later version.
00008 
00009    The GNU C Library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Lesser General Public License for more details.
00013 
00014    You should have received a copy of the GNU Lesser General Public
00015    License along with the GNU C Library; if not, write to the Free
00016    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00017    02111-1307 USA.  */
00018 
00019 #include <stdint.h>
00020 #include <sysdep.h>
00021 
00022 
00023 typedef int8_t atomic8_t;
00024 typedef uint8_t uatomic8_t;
00025 typedef int_fast8_t atomic_fast8_t;
00026 typedef uint_fast8_t uatomic_fast8_t;
00027 
00028 typedef int32_t atomic32_t;
00029 typedef uint32_t uatomic32_t;
00030 typedef int_fast32_t atomic_fast32_t;
00031 typedef uint_fast32_t uatomic_fast32_t;
00032 
00033 typedef intptr_t atomicptr_t;
00034 typedef uintptr_t uatomicptr_t;
00035 typedef intmax_t atomic_max_t;
00036 typedef uintmax_t uatomic_max_t;
00037 
00038 void __arm_link_error (void);
00039 
00040 #define atomic_exchange_acq(mem, newvalue)                                  \
00041   ({ __typeof (*mem) result;                                                \
00042      if (sizeof (*mem) == 1)                                                \
00043        __asm__ __volatile__ ("swpb %0, %1, [%2]"                     \
00044                           : "=&r,&r" (result)                        \
00045                           : "r,0" (newvalue), "r,r" (mem) : "memory");     \
00046      else if (sizeof (*mem) == 4)                                    \
00047        __asm__ __volatile__ ("swp %0, %1, [%2]"                             \
00048                           : "=&r,&r" (result)                        \
00049                           : "r,0" (newvalue), "r,r" (mem) : "memory");     \
00050      else                                                            \
00051        {                                                             \
00052         result = 0;                                                  \
00053         abort ();                                                    \
00054        }                                                             \
00055      result; })
00056 
00057 /* Atomic compare and exchange.  These sequences are not actually atomic;
00058    there is a race if *MEM != OLDVAL and we are preempted between the two
00059    swaps.  However, they are very close to atomic, and are the best that a
00060    pre-ARMv6 implementation can do without operating system support.
00061    LinuxThreads has been using these sequences for many years.  */
00062 
00063 #define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \
00064   ({ __typeof (oldval) result, tmp;                                         \
00065      __asm__ ("\n"                                                   \
00066              "0:\tldr\t%1,[%2]\n\t"                                         \
00067              "cmp\t%1,%4\n\t"                                               \
00068              "movne\t%0,%1\n\t"                                      \
00069              "bne\t1f\n\t"                                           \
00070              "swpb\t%0,%3,[%2]\n\t"                                         \
00071              "cmp\t%1,%0\n\t"                                               \
00072              "swpbne\t%1,%0,[%2]\n\t"                                       \
00073              "bne\t0b\n\t"                                           \
00074              "1:"                                                    \
00075              : "=&r" (result), "=&r" (tmp)                                  \
00076              : "r" (mem), "r" (newval), "r" (oldval)                        \
00077              : "cc", "memory");                                      \
00078      result; })
00079 
00080 #define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \
00081   ({ __arm_link_error (); oldval; })
00082 
00083 #define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \
00084   ({ __typeof (oldval) result, tmp;                                         \
00085      __asm__ ("\n"                                                   \
00086              "0:\tldr\t%1,[%2]\n\t"                                         \
00087              "cmp\t%1,%4\n\t"                                               \
00088              "movne\t%0,%1\n\t"                                      \
00089              "bne\t1f\n\t"                                           \
00090              "swp\t%0,%3,[%2]\n\t"                                   \
00091              "cmp\t%1,%0\n\t"                                               \
00092              "swpne\t%1,%0,[%2]\n\t"                                        \
00093              "bne\t0b\n\t"                                           \
00094              "1:"                                                    \
00095              : "=&r" (result), "=&r" (tmp)                                  \
00096              : "r" (mem), "r" (newval), "r" (oldval)                        \
00097              : "cc", "memory");                                      \
00098      result; })
00099 
00100 #define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \
00101   ({ __arm_link_error (); oldval; })