Back to index

glibc  2.9
atomic.h
Go to the documentation of this file.
00001 /* Atomic operations.  PowerPC Common version.
00002    Copyright (C) 2003, 2004 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 /*
00022  * Never include sysdeps/powerpc/bits/atomic.h directly.
00023  * Alway use include/atomic.h which will include either
00024  * sysdeps/powerpc/powerpc32/bits/atomic.h
00025  * or
00026  * sysdeps/powerpc/powerpc64/bits/atomic.h
00027  * as appropriate and which in turn include this file.
00028  */
00029 
00030 #include <stdint.h>
00031 
00032 typedef int32_t atomic32_t;
00033 typedef uint32_t uatomic32_t;
00034 typedef int_fast32_t atomic_fast32_t;
00035 typedef uint_fast32_t uatomic_fast32_t;
00036 
00037 typedef int64_t atomic64_t;
00038 typedef uint64_t uatomic64_t;
00039 typedef int_fast64_t atomic_fast64_t;
00040 typedef uint_fast64_t uatomic_fast64_t;
00041 
00042 typedef intptr_t atomicptr_t;
00043 typedef uintptr_t uatomicptr_t;
00044 typedef intmax_t atomic_max_t;
00045 typedef uintmax_t uatomic_max_t;
00046 
00047 /*
00048  * Powerpc does not have byte and halfword forms of load and reserve and
00049  * store conditional. So for powerpc we stub out the 8- and 16-bit forms.
00050  */
00051 #define __arch_compare_and_exchange_bool_8_acq(mem, newval, oldval) \
00052   (abort (), 0)
00053 
00054 #define __arch_compare_and_exchange_bool_16_acq(mem, newval, oldval) \
00055   (abort (), 0)
00056 
00057 #define __arch_compare_and_exchange_bool_8_rel(mem, newval, oldval) \
00058   (abort (), 0)
00059 
00060 #define __arch_compare_and_exchange_bool_16_rel(mem, newval, oldval) \
00061   (abort (), 0)
00062 
00063 #ifdef UP
00064 # define __ARCH_ACQ_INSTR   ""
00065 # define __ARCH_REL_INSTR   ""
00066 #else
00067 # define __ARCH_ACQ_INSTR   "isync"
00068 # ifndef __ARCH_REL_INSTR
00069 #  define __ARCH_REL_INSTR  "sync"
00070 # endif
00071 #endif
00072 
00073 #ifndef MUTEX_HINT_ACQ
00074 # define MUTEX_HINT_ACQ
00075 #endif
00076 #ifndef MUTEX_HINT_REL
00077 # define MUTEX_HINT_REL
00078 #endif
00079 
00080 #define atomic_full_barrier()      __asm ("sync" ::: "memory")
00081 #define atomic_write_barrier()     __asm ("eieio" ::: "memory")
00082 
00083 #define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval)         \
00084   ({                                                                 \
00085       __typeof (*(mem)) __tmp;                                              \
00086       __typeof (mem)  __memp = (mem);                                       \
00087       __asm __volatile (                                             \
00088                       "1:   lwarx  %0,0,%1" MUTEX_HINT_ACQ "\n"             \
00089                       "     cmpw   %0,%2\n"                          \
00090                       "     bne    2f\n"                             \
00091                       "     stwcx. %3,0,%1\n"                        \
00092                       "     bne-   1b\n"                             \
00093                       "2:   " __ARCH_ACQ_INSTR                       \
00094                       : "=&r" (__tmp)                                       \
00095                       : "b" (__memp), "r" (oldval), "r" (newval)            \
00096                       : "cr0", "memory");                            \
00097       __tmp;                                                         \
00098   })
00099 
00100 #define __arch_compare_and_exchange_val_32_rel(mem, newval, oldval)         \
00101   ({                                                                 \
00102       __typeof (*(mem)) __tmp;                                              \
00103       __typeof (mem)  __memp = (mem);                                       \
00104       __asm __volatile (__ARCH_REL_INSTR "\n"                               \
00105                       "1:   lwarx  %0,0,%1" MUTEX_HINT_REL "\n"             \
00106                       "     cmpw   %0,%2\n"                          \
00107                       "     bne    2f\n"                             \
00108                       "     stwcx. %3,0,%1\n"                        \
00109                       "     bne-   1b\n"                             \
00110                       "2:   "                                        \
00111                       : "=&r" (__tmp)                                       \
00112                       : "b" (__memp), "r" (oldval), "r" (newval)            \
00113                       : "cr0", "memory");                            \
00114       __tmp;                                                         \
00115   })
00116 
00117 #define __arch_atomic_exchange_32_acq(mem, value)                           \
00118   ({                                                                 \
00119     __typeof (*mem) __val;                                           \
00120     __asm __volatile (                                                      \
00121                     "1:     lwarx  %0,0,%2" MUTEX_HINT_ACQ "\n"             \
00122                     "              stwcx. %3,0,%2\n"                        \
00123                     "              bne-   1b\n"                             \
00124                     "   " __ARCH_ACQ_INSTR                                  \
00125                     : "=&r" (__val), "=m" (*mem)                     \
00126                     : "b" (mem), "r" (value), "m" (*mem)                    \
00127                     : "cr0", "memory");                              \
00128     __val;                                                           \
00129   })
00130 
00131 #define __arch_atomic_exchange_32_rel(mem, value) \
00132   ({                                                                 \
00133     __typeof (*mem) __val;                                           \
00134     __asm __volatile (__ARCH_REL_INSTR "\n"                                 \
00135                     "1:     lwarx  %0,0,%2" MUTEX_HINT_REL "\n"             \
00136                     "              stwcx. %3,0,%2\n"                        \
00137                     "              bne-   1b"                               \
00138                     : "=&r" (__val), "=m" (*mem)                     \
00139                     : "b" (mem), "r" (value), "m" (*mem)                    \
00140                     : "cr0", "memory");                              \
00141     __val;                                                           \
00142   })
00143 
00144 #define __arch_atomic_exchange_and_add_32(mem, value) \
00145   ({                                                                 \
00146     __typeof (*mem) __val, __tmp;                                    \
00147     __asm __volatile ("1:   lwarx  %0,0,%3\n"                        \
00148                     "              add    %1,%0,%4\n"                       \
00149                     "              stwcx. %1,0,%3\n"                        \
00150                     "              bne-   1b"                               \
00151                     : "=&b" (__val), "=&r" (__tmp), "=m" (*mem)             \
00152                     : "b" (mem), "r" (value), "m" (*mem)                    \
00153                     : "cr0", "memory");                              \
00154     __val;                                                           \
00155   })
00156 
00157 #define __arch_atomic_increment_val_32(mem) \
00158   ({                                                                 \
00159     __typeof (*(mem)) __val;                                                \
00160     __asm __volatile ("1:   lwarx  %0,0,%2\n"                        \
00161                     "              addi   %0,%0,1\n"                        \
00162                     "              stwcx. %0,0,%2\n"                        \
00163                     "              bne-   1b"                               \
00164                     : "=&b" (__val), "=m" (*mem)                     \
00165                     : "b" (mem), "m" (*mem)                                 \
00166                     : "cr0", "memory");                              \
00167     __val;                                                           \
00168   })
00169 
00170 #define __arch_atomic_decrement_val_32(mem) \
00171   ({                                                                 \
00172     __typeof (*(mem)) __val;                                                \
00173     __asm __volatile ("1:   lwarx  %0,0,%2\n"                        \
00174                     "              subi   %0,%0,1\n"                        \
00175                     "              stwcx. %0,0,%2\n"                        \
00176                     "              bne-   1b"                               \
00177                     : "=&b" (__val), "=m" (*mem)                     \
00178                     : "b" (mem), "m" (*mem)                                 \
00179                     : "cr0", "memory");                              \
00180     __val;                                                           \
00181   })
00182 
00183 #define __arch_atomic_decrement_if_positive_32(mem) \
00184   ({ int __val, __tmp;                                                      \
00185      __asm __volatile ("1:  lwarx  %0,0,%3\n"                        \
00186                      "      cmpwi  0,%0,0\n"                         \
00187                      "      addi   %1,%0,-1\n"                       \
00188                      "      ble    2f\n"                             \
00189                      "      stwcx. %1,0,%3\n"                        \
00190                      "      bne-   1b\n"                             \
00191                      "2:    " __ARCH_ACQ_INSTR                       \
00192                      : "=&b" (__val), "=&r" (__tmp), "=m" (*mem)            \
00193                      : "b" (mem), "m" (*mem)                                \
00194                      : "cr0", "memory");                             \
00195      __val;                                                          \
00196   })
00197 
00198 #define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
00199   ({                                                                 \
00200     __typeof (*(mem)) __result;                                             \
00201     if (sizeof (*mem) == 4)                                          \
00202       __result = __arch_compare_and_exchange_val_32_acq(mem, newval, oldval); \
00203     else if (sizeof (*mem) == 8)                                     \
00204       __result = __arch_compare_and_exchange_val_64_acq(mem, newval, oldval); \
00205     else                                                             \
00206        abort ();                                                     \
00207     __result;                                                        \
00208   })
00209 
00210 #define atomic_compare_and_exchange_val_rel(mem, newval, oldval) \
00211   ({                                                                 \
00212     __typeof (*(mem)) __result;                                             \
00213     if (sizeof (*mem) == 4)                                          \
00214       __result = __arch_compare_and_exchange_val_32_rel(mem, newval, oldval); \
00215     else if (sizeof (*mem) == 8)                                     \
00216       __result = __arch_compare_and_exchange_val_64_rel(mem, newval, oldval); \
00217     else                                                             \
00218        abort ();                                                     \
00219     __result;                                                        \
00220   })
00221 
00222 #define atomic_exchange_acq(mem, value) \
00223   ({                                                                 \
00224     __typeof (*(mem)) __result;                                             \
00225     if (sizeof (*mem) == 4)                                          \
00226       __result = __arch_atomic_exchange_32_acq (mem, value);                \
00227     else if (sizeof (*mem) == 8)                                     \
00228       __result = __arch_atomic_exchange_64_acq (mem, value);                \
00229     else                                                             \
00230        abort ();                                                     \
00231     __result;                                                        \
00232   })
00233 
00234 #define atomic_exchange_rel(mem, value) \
00235   ({                                                                 \
00236     __typeof (*(mem)) __result;                                             \
00237     if (sizeof (*mem) == 4)                                          \
00238       __result = __arch_atomic_exchange_32_rel (mem, value);                \
00239     else if (sizeof (*mem) == 8)                                     \
00240       __result = __arch_atomic_exchange_64_rel (mem, value);                \
00241     else                                                             \
00242        abort ();                                                     \
00243     __result;                                                        \
00244   })
00245 
00246 #define atomic_exchange_and_add(mem, value) \
00247   ({                                                                 \
00248     __typeof (*(mem)) __result;                                             \
00249     if (sizeof (*mem) == 4)                                          \
00250       __result = __arch_atomic_exchange_and_add_32 (mem, value);            \
00251     else if (sizeof (*mem) == 8)                                     \
00252       __result = __arch_atomic_exchange_and_add_64 (mem, value);            \
00253     else                                                             \
00254        abort ();                                                     \
00255     __result;                                                        \
00256   })
00257 
00258 #define atomic_increment_val(mem) \
00259   ({                                                                 \
00260     __typeof (*(mem)) __result;                                             \
00261     if (sizeof (*(mem)) == 4)                                               \
00262       __result = __arch_atomic_increment_val_32 (mem);                      \
00263     else if (sizeof (*(mem)) == 8)                                   \
00264       __result = __arch_atomic_increment_val_64 (mem);                      \
00265     else                                                             \
00266        abort ();                                                     \
00267     __result;                                                        \
00268   })
00269 
00270 #define atomic_increment(mem) ({ atomic_increment_val (mem); (void) 0; })
00271 
00272 #define atomic_decrement_val(mem) \
00273   ({                                                                 \
00274     __typeof (*(mem)) __result;                                             \
00275     if (sizeof (*(mem)) == 4)                                               \
00276       __result = __arch_atomic_decrement_val_32 (mem);                      \
00277     else if (sizeof (*(mem)) == 8)                                   \
00278       __result = __arch_atomic_decrement_val_64 (mem);                      \
00279     else                                                             \
00280        abort ();                                                     \
00281     __result;                                                        \
00282   })
00283 
00284 #define atomic_decrement(mem) ({ atomic_decrement_val (mem); (void) 0; })
00285 
00286 
00287 /* Decrement *MEM if it is > 0, and return the old value.  */
00288 #define atomic_decrement_if_positive(mem) \
00289   ({ __typeof (*(mem)) __result;                                     \
00290     if (sizeof (*mem) == 4)                                          \
00291       __result = __arch_atomic_decrement_if_positive_32 (mem);              \
00292     else if (sizeof (*mem) == 8)                                     \
00293       __result = __arch_atomic_decrement_if_positive_64 (mem);              \
00294     else                                                             \
00295        abort ();                                                     \
00296     __result;                                                        \
00297   })