Back to index

glibc  2.9
atomic.h
Go to the documentation of this file.
00001 /* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Contributed by Andreas Schwab <schwab@suse.de>, 2003.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <stdint.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 int16_t atomic16_t;
00029 typedef uint16_t uatomic16_t;
00030 typedef int_fast16_t atomic_fast16_t;
00031 typedef uint_fast16_t uatomic_fast16_t;
00032 
00033 typedef int32_t atomic32_t;
00034 typedef uint32_t uatomic32_t;
00035 typedef int_fast32_t atomic_fast32_t;
00036 typedef uint_fast32_t uatomic_fast32_t;
00037 
00038 typedef int64_t atomic64_t;
00039 typedef uint64_t uatomic64_t;
00040 typedef int_fast64_t atomic_fast64_t;
00041 typedef uint_fast64_t uatomic_fast64_t;
00042 
00043 typedef intptr_t atomicptr_t;
00044 typedef uintptr_t uatomicptr_t;
00045 typedef intmax_t atomic_max_t;
00046 typedef uintmax_t uatomic_max_t;
00047 
00048 #define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \
00049   ({ __typeof (*(mem)) __ret;                                               \
00050      __asm __volatile ("cas%.b %0,%2,%1"                             \
00051                      : "=d" (__ret), "+m" (*(mem))                          \
00052                      : "d" (newval), "0" (oldval));                         \
00053      __ret; })
00054 
00055 #define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \
00056   ({ __typeof (*(mem)) __ret;                                               \
00057      __asm __volatile ("cas%.w %0,%2,%1"                             \
00058                      : "=d" (__ret), "+m" (*(mem))                          \
00059                      : "d" (newval), "0" (oldval));                         \
00060      __ret; })
00061 
00062 #define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \
00063   ({ __typeof (*(mem)) __ret;                                               \
00064      __asm __volatile ("cas%.l %0,%2,%1"                             \
00065                      : "=d" (__ret), "+m" (*(mem))                          \
00066                      : "d" (newval), "0" (oldval));                         \
00067      __ret; })
00068 
00069 # define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \
00070   ({ __typeof (*(mem)) __ret;                                               \
00071      __typeof (mem) __memp = (mem);                                         \
00072      __asm __volatile ("cas2%.l %0:%R0,%1:%R1,(%2):(%3)"                    \
00073                      : "=d" (__ret)                                         \
00074                      : "d" (newval), "r" (__memp),                          \
00075                       "r" ((char *) __memp + 4), "0" (oldval)        \
00076                      : "memory");                                    \
00077      __ret; })
00078 
00079 #define atomic_exchange_acq(mem, newvalue) \
00080   ({ __typeof (*(mem)) __result = *(mem);                            \
00081      if (sizeof (*(mem)) == 1)                                              \
00082        __asm __volatile ("1: cas%.b %0,%2,%1;"                              \
00083                       "   jbne 1b"                                   \
00084                       : "=d" (__result), "+m" (*(mem))               \
00085                       : "d" (newvalue), "0" (__result));                    \
00086      else if (sizeof (*(mem)) == 2)                                         \
00087        __asm __volatile ("1: cas%.w %0,%2,%1;"                              \
00088                       "   jbne 1b"                                   \
00089                       : "=d" (__result), "+m" (*(mem))               \
00090                       : "d" (newvalue), "0" (__result));                    \
00091      else if (sizeof (*(mem)) == 4)                                         \
00092        __asm __volatile ("1: cas%.l %0,%2,%1;"                              \
00093                       "   jbne 1b"                                   \
00094                       : "=d" (__result), "+m" (*(mem))               \
00095                       : "d" (newvalue), "0" (__result));                    \
00096      else                                                            \
00097        {                                                             \
00098         __typeof (mem) __memp = (mem);                                      \
00099         __asm __volatile ("1: cas2%.l %0:%R0,%1:%R1,(%2):(%3);"             \
00100                         "   jbne 1b"                                        \
00101                         : "=d" (__result)                            \
00102                         : "d" (newvalue), "r" (__memp),              \
00103                           "r" ((char *) __memp + 4), "0" (__result)         \
00104                         : "memory");                                        \
00105        }                                                             \
00106      __result; })
00107 
00108 #define atomic_exchange_and_add(mem, value) \
00109   ({ __typeof (*(mem)) __result = *(mem);                            \
00110      __typeof (*(mem)) __temp;                                              \
00111      if (sizeof (*(mem)) == 1)                                              \
00112        __asm __volatile ("1: move%.b %0,%2;"                                \
00113                       "   add%.b %3,%2;"                             \
00114                       "   cas%.b %0,%2,%1;"                                 \
00115                       "   jbne 1b"                                   \
00116                       : "=d" (__result), "+m" (*(mem)),              \
00117                         "=&d" (__temp)                               \
00118                       : "d" (value), "0" (__result));                \
00119      else if (sizeof (*(mem)) == 2)                                         \
00120        __asm __volatile ("1: move%.w %0,%2;"                                \
00121                       "   add%.w %3,%2;"                             \
00122                       "   cas%.w %0,%2,%1;"                                 \
00123                       "   jbne 1b"                                   \
00124                       : "=d" (__result), "+m" (*(mem)),              \
00125                         "=&d" (__temp)                               \
00126                       : "d" (value), "0" (__result));                \
00127      else if (sizeof (*(mem)) == 4)                                         \
00128        __asm __volatile ("1: move%.l %0,%2;"                                \
00129                       "   add%.l %3,%2;"                             \
00130                       "   cas%.l %0,%2,%1;"                                 \
00131                       "   jbne 1b"                                   \
00132                       : "=d" (__result), "+m" (*(mem)),              \
00133                         "=&d" (__temp)                               \
00134                       : "d" (value), "0" (__result));                \
00135      else                                                            \
00136        {                                                             \
00137         __typeof (mem) __memp = (mem);                                      \
00138         __asm __volatile ("1: move%.l %0,%1;"                               \
00139                         "   move%.l %R0,%R1;"                        \
00140                         "   add%.l %2,%1;"                                  \
00141                         "   addx%.l %R2,%R1;"                        \
00142                         "   cas2%.l %0:%R0,%1:%R1,(%3):(%4);"        \
00143                         "   jbne 1b"                                        \
00144                         : "=d" (__result), "=&d" (__temp)                   \
00145                         : "d" (value), "r" (__memp),                        \
00146                           "r" ((char *) __memp + 4), "0" (__result)         \
00147                         : "memory");                                        \
00148        }                                                             \
00149      __result; })
00150 
00151 #define atomic_add(mem, value) \
00152   (void) ({ if (sizeof (*(mem)) == 1)                                       \
00153              __asm __volatile ("add%.b %1,%0"                               \
00154                             : "+m" (*(mem))                                 \
00155                             : "id" (value));                         \
00156            else if (sizeof (*(mem)) == 2)                            \
00157              __asm __volatile ("add%.w %1,%0"                               \
00158                             : "+m" (*(mem))                                 \
00159                             : "id" (value));                         \
00160            else if (sizeof (*(mem)) == 4)                            \
00161              __asm __volatile ("add%.l %1,%0"                               \
00162                             : "+m" (*(mem))                                 \
00163                             : "id" (value));                         \
00164            else                                                      \
00165              {                                                              \
00166               __typeof (mem) __memp = (mem);                                \
00167               __typeof (*(mem)) __oldval = *__memp;                         \
00168               __typeof (*(mem)) __temp;                              \
00169               __asm __volatile ("1: move%.l %0,%1;"                         \
00170                               "   move%.l %R0,%R1;"                         \
00171                               "   add%.l %2,%1;"                     \
00172                               "   addx%.l %R2,%R1;"                         \
00173                               "   cas2%.l %0:%R0,%1:%R1,(%3):(%4);"         \
00174                               "   jbne 1b"                                  \
00175                               : "=d" (__oldval), "=&d" (__temp)             \
00176                               : "d" (value), "r" (__memp),                  \
00177                                 "r" ((char *) __memp + 4), "0" (__oldval) \
00178                               : "memory");                                  \
00179              }                                                              \
00180            })
00181 
00182 #define atomic_increment_and_test(mem) \
00183   ({ char __result;                                                  \
00184      if (sizeof (*(mem)) == 1)                                              \
00185        __asm __volatile ("addq%.b %#1,%1; seq %0"                           \
00186                       : "=dm" (__result), "+m" (*(mem)));                   \
00187      else if (sizeof (*(mem)) == 2)                                         \
00188        __asm __volatile ("addq%.w %#1,%1; seq %0"                           \
00189                       : "=dm" (__result), "+m" (*(mem)));                   \
00190      else if (sizeof (*(mem)) == 4)                                         \
00191        __asm __volatile ("addq%.l %#1,%1; seq %0"                           \
00192                       : "=dm" (__result), "+m" (*(mem)));                   \
00193      else                                                            \
00194        {                                                             \
00195         __typeof (mem) __memp = (mem);                                      \
00196         __typeof (*(mem)) __oldval = *__memp;                               \
00197         __typeof (*(mem)) __temp;                                    \
00198         __asm __volatile ("1: move%.l %1,%2;"                               \
00199                         "   move%.l %R1,%R2;"                        \
00200                         "   addq%.l %#1,%2;"                                \
00201                         "   addx%.l %5,%R2;"                                \
00202                         "   seq %0;"                                        \
00203                         "   cas2%.l %1:%R1,%2:%R2,(%3):(%4);"        \
00204                         "   jbne 1b"                                        \
00205                         : "=&dm" (__result), "=d" (__oldval),        \
00206                           "=&d" (__temp)                             \
00207                         : "r" (__memp), "r" ((char *) __memp + 4),          \
00208                           "d" (0), "1" (__oldval)                           \
00209                         : "memory");                                        \
00210        }                                                             \
00211      __result; })
00212 
00213 #define atomic_decrement_and_test(mem) \
00214   ({ char __result;                                                  \
00215      if (sizeof (*(mem)) == 1)                                              \
00216        __asm __volatile ("subq%.b %#1,%1; seq %0"                           \
00217                       : "=dm" (__result), "+m" (*(mem)));                   \
00218      else if (sizeof (*(mem)) == 2)                                         \
00219        __asm __volatile ("subq%.w %#1,%1; seq %0"                           \
00220                       : "=dm" (__result), "+m" (*(mem)));                   \
00221      else if (sizeof (*(mem)) == 4)                                         \
00222        __asm __volatile ("subq%.l %#1,%1; seq %0"                           \
00223                       : "=dm" (__result), "+m" (*(mem)));                   \
00224      else                                                            \
00225        {                                                             \
00226         __typeof (mem) __memp = (mem);                                      \
00227         __typeof (*(mem)) __oldval = *__memp;                               \
00228         __typeof (*(mem)) __temp;                                    \
00229         __asm __volatile ("1: move%.l %1,%2;"                               \
00230                         "   move%.l %R1,%R2;"                        \
00231                         "   subq%.l %#1,%2;"                                \
00232                         "   subx%.l %5,%R2;"                                \
00233                         "   seq %0;"                                        \
00234                         "   cas2%.l %1:%R1,%2:%R2,(%3):(%4);"        \
00235                         "   jbne 1b"                                        \
00236                         : "=&dm" (__result), "=d" (__oldval),        \
00237                           "=&d" (__temp)                             \
00238                         : "r" (__memp), "r" ((char *) __memp + 4),          \
00239                           "d" (0), "1" (__oldval)                           \
00240                         : "memory");                                        \
00241        }                                                             \
00242      __result; })
00243 
00244 #define atomic_bit_set(mem, bit) \
00245   __asm __volatile ("bfset %0{%1,#1}"                                       \
00246                   : "+m" (*(mem))                                    \
00247                   : "di" (sizeof (*(mem)) * 8 - (bit) - 1))
00248 
00249 #define atomic_bit_test_set(mem, bit) \
00250   ({ char __result;                                                  \
00251      __asm __volatile ("bfset %1{%2,#1}; sne %0"                     \
00252                      : "=dm" (__result), "+m" (*(mem))               \
00253                      : "di" (sizeof (*(mem)) * 8 - (bit) - 1));             \
00254      __result; })