oro_atomic.h
Go to the documentation of this file.
00001 /***************************************************************************
00002  tag: FMTC  Tue Mar 11 21:49:19 CET 2008  oro_atomic.h
00003 
00004  oro_atomic.h -  description
00005  -------------------
00006  begin                : Tue March 11 2008
00007  copyright            : (C) 2008 FMTC
00008  email                : peter.soetens@fmtc.be
00009 
00010  ***************************************************************************
00011  *   This library is free software; you can redistribute it and/or         *
00012  *   modify it under the terms of the GNU General Public                   *
00013  *   License as published by the Free Software Foundation;                 *
00014  *   version 2 of the License.                                             *
00015  *                                                                         *
00016  *   As a special exception, you may use this file as part of a free       *
00017  *   software library without restriction.  Specifically, if other files   *
00018  *   instantiate templates or use macros or inline functions from this     *
00019  *   file, or you compile this file and link it with other files to        *
00020  *   produce an executable, this file does not by itself cause the         *
00021  *   resulting executable to be covered by the GNU General Public          *
00022  *   License.  This exception does not however invalidate any other        *
00023  *   reasons why the executable file might be covered by the GNU General   *
00024  *   Public License.                                                       *
00025  *                                                                         *
00026  *   This library is distributed in the hope that it will be useful,       *
00027  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00028  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00029  *   Lesser General Public License for more details.                       *
00030  *                                                                         *
00031  *   You should have received a copy of the GNU General Public             *
00032  *   License along with this library; if not, write to the Free Software   *
00033  *   Foundation, Inc., 59 Temple Place,                                    *
00034  *   Suite 330, Boston, MA  02111-1307  USA                                *
00035  *                                                                         *
00036  ***************************************************************************/
00037 
00038 #ifndef __ARCH_powerpc_ORO_ATOMIC__
00039 #define __ARCH_powerpc_ORO_ATOMIC__
00040 
00041 /* Klaas Gadeyne, copied the 32 bit part from
00042  * /usr/src/linux-2.6.16/include/asm-powerpc/atomic.h
00043  * /usr/src/linux-2.6.16/include/asm-powerpc/asm-compat.h
00044  * /usr/src/linux-2.6.16/include/asm-powerpc/synch.h
00045  * So will currently only work for 32 bit ppc
00046  */
00047 
00048 // ==================================================
00049 // asm/synch.h
00050 #ifdef _cplusplus
00051 extern "C"
00052 {
00053 #endif // _cplusplus
00054 #ifdef __SUBARCH_HAS_LWSYNC
00055 #    define LWSYNC      lwsync
00056 #else
00057 #    define LWSYNC      sync
00058 #endif
00059 
00060 #define ISYNC_ON_SMP
00061 #define LWSYNC_ON_SMP
00062 
00063 static inline void eieio(void)
00064 {
00065   __asm__ __volatile__ ("eieio" : : : "memory");
00066 }
00067 
00068 static inline void isync(void)
00069 {
00070   __asm__ __volatile__ ("isync" : : : "memory");
00071 }
00072 
00073 // ==================================================
00074 // asm/asm-compat.h
00075 
00076 #ifdef __ASSEMBLY__
00077 #  define stringify_in_c(...)   __VA_ARGS__
00078 #  define ASM_CONST(x)          x
00079 #else
00080 /* This version of stringify will deal with commas... */
00081 #  define __stringify_in_c(...) #__VA_ARGS__
00082 #  define stringify_in_c(...)   __stringify_in_c(__VA_ARGS__) " "
00083 #  define __ASM_CONST(x)        x##UL
00084 #  define ASM_CONST(x)          __ASM_CONST(x)
00085 #endif
00086 
00087 /* operations for longs and pointers */
00088 #define PPC_LL          stringify_in_c(lwz)
00089 #define PPC_STL         stringify_in_c(stw)
00090 #define PPC_LCMPI       stringify_in_c(cmpwi)
00091 #define PPC_LONG        stringify_in_c(.long)
00092 #define PPC_TLNEI       stringify_in_c(twnei)
00093 #define PPC_LLARX       stringify_in_c(lwarx)
00094 #define PPC_STLCX       stringify_in_c(stwcx.)
00095 #define PPC_CNTLZL      stringify_in_c(cntlzw)
00096 
00097 #ifdef CONFIG_IBM405_ERR77
00098 /* Erratum #77 on the 405 means we need a sync or dcbt before every
00099  * stwcx.  The old ATOMIC_SYNC_FIX covered some but not all of this.
00100  */
00101 #define PPC405_ERR77(ra,rb)     stringify_in_c(dcbt     ra, rb;)
00102 #define PPC405_ERR77_SYNC       stringify_in_c(sync;)
00103 #else
00104 #define PPC405_ERR77(ra,rb)
00105 #define PPC405_ERR77_SYNC
00106 #endif
00107 
00108 // ==================================================
00109 // asm/atomic.h
00110 
00111 /*
00112  * PowerPC atomic operations
00113  */
00114 
00115 typedef struct
00116 {
00117   volatile int counter;
00118 } oro_atomic_t;
00119 
00120 #define ORO_ATOMIC_INIT(i)              { (i) }
00121 #define ORO_ATOMIC_SETUP        oro_atomic_set
00122 #define ORO_ATOMIC_CLEANUP(v)   
00123 
00124 #define oro_atomic_read(v)              ((v)->counter)
00125 #define oro_atomic_set(v,i)             (((v)->counter) = (i))
00126 
00127 static __inline__ void oro_atomic_add(oro_atomic_t *v, int n)
00128 {
00129   int t;
00130 
00131   __asm__ __volatile__(
00132       "1:       lwarx   %0,0,%3         # oro_atomic_add\n\
00133         add     %0,%2,%0\n"
00134       PPC405_ERR77(0,%3)
00135       " stwcx.  %0,0,%3 \n\
00136         bne-    1b"
00137       : "=&r" (t), "=m" (v->counter)
00138       : "r" (a), "r" (&v->counter), "m" (v->counter)
00139       : "cc");
00140 }
00141 
00142 static __inline__ int oro_atomic_add_return(oro_atomic_t *v, int n)
00143 {
00144   int t;
00145 
00146   __asm__ __volatile__(
00147       LWSYNC_ON_SMP
00148       "1:       lwarx   %0,0,%2         # oro_atomic_add_return\n\
00149         add     %0,%1,%0\n"
00150       PPC405_ERR77(0,%2)
00151       " stwcx.  %0,0,%2 \n\
00152         bne-    1b"
00153       ISYNC_ON_SMP
00154       : "=&r" (t)
00155       : "r" (a), "r" (&v->counter)
00156       : "cc", "memory");
00157 
00158   return t;
00159 }
00160 
00161 #define oro_atomic_add_negative(a, v)   (oro_atomic_add_return((a), (v)) < 0)
00162 
00163 static __inline__ void oro_atomic_sub(int a, oro_atomic_t *v)
00164 {
00165   int t;
00166 
00167   __asm__ __volatile__(
00168       "1:       lwarx   %0,0,%3         # oro_atomic_sub\n\
00169         subf    %0,%2,%0\n"
00170       PPC405_ERR77(0,%3)
00171       " stwcx.  %0,0,%3 \n\
00172         bne-    1b"
00173       : "=&r" (t), "=m" (v->counter)
00174       : "r" (a), "r" (&v->counter), "m" (v->counter)
00175       : "cc");
00176 }
00177 
00178 static __inline__ int oro_atomic_sub_return(oro_atomic_t *v, int n)
00179 {
00180   int t;
00181 
00182   __asm__ __volatile__(
00183       LWSYNC_ON_SMP
00184       "1:       lwarx   %0,0,%2         # oro_atomic_sub_return\n\
00185         subf    %0,%1,%0\n"
00186       PPC405_ERR77(0,%2)
00187       " stwcx.  %0,0,%2 \n\
00188         bne-    1b"
00189       ISYNC_ON_SMP
00190       : "=&r" (t)
00191       : "r" (a), "r" (&v->counter)
00192       : "cc", "memory");
00193 
00194   return t;
00195 }
00196 
00197 static __inline__ void oro_atomic_inc(oro_atomic_t *v)
00198 {
00199   int t;
00200 
00201   __asm__ __volatile__(
00202       "1:       lwarx   %0,0,%2         # oro_atomic_inc\n\
00203         addic   %0,%0,1\n"
00204       PPC405_ERR77(0,%2)
00205       " stwcx.  %0,0,%2 \n\
00206         bne-    1b"
00207       : "=&r" (t), "=m" (v->counter)
00208       : "r" (&v->counter), "m" (v->counter)
00209       : "cc");
00210 }
00211 
00212 static __inline__ int oro_atomic_inc_return(oro_atomic_t *v)
00213 {
00214   int t;
00215 
00216   __asm__ __volatile__(
00217       LWSYNC_ON_SMP
00218       "1:       lwarx   %0,0,%1         # oro_atomic_inc_return\n\
00219         addic   %0,%0,1\n"
00220       PPC405_ERR77(0,%1)
00221       " stwcx.  %0,0,%1 \n\
00222         bne-    1b"
00223       ISYNC_ON_SMP
00224       : "=&r" (t)
00225       : "r" (&v->counter)
00226       : "cc", "memory");
00227 
00228   return t;
00229 }
00230 
00231 /*
00232  * oro_atomic_inc_and_test - increment and test
00233  * @v: pointer of type oro_atomic_t
00234  *
00235  * Atomically increments @v by 1
00236  * and returns true if the result is zero, or false for all
00237  * other cases.
00238  */
00239 #define oro_atomic_inc_and_test(v) (oro_atomic_inc_return(v) == 0)
00240 
00241 static __inline__ void oro_atomic_dec(oro_atomic_t *v)
00242 {
00243   int t;
00244 
00245   __asm__ __volatile__(
00246       "1:       lwarx   %0,0,%2         # oro_atomic_dec\n\
00247         addic   %0,%0,-1\n"
00248       PPC405_ERR77(0,%2)\
00249 "       stwcx.  %0,0,%2\n\
00250         bne-    1b"
00251       : "=&r" (t), "=m" (v->counter)
00252       : "r" (&v->counter), "m" (v->counter)
00253       : "cc");
00254 }
00255 
00256 static __inline__ int oro_atomic_dec_return(oro_atomic_t *v)
00257 {
00258   int t;
00259 
00260   __asm__ __volatile__(
00261       LWSYNC_ON_SMP
00262       "1:       lwarx   %0,0,%1         # oro_atomic_dec_return\n\
00263         addic   %0,%0,-1\n"
00264       PPC405_ERR77(0,%1)
00265       " stwcx.  %0,0,%1\n\
00266         bne-    1b"
00267       ISYNC_ON_SMP
00268       : "=&r" (t)
00269       : "r" (&v->counter)
00270       : "cc", "memory");
00271 
00272   return t;
00273 }
00274 
00275 #define oro_atomic_oro_cmpxchg(v, o, n) ((int)oro_cmpxchg(&((v)->counter), (o), (n)))
00276 #define oro_atomic_xchg(v, new) (xchg(&((v)->counter), new))
00277 
00287 #define oro_atomic_add_unless(v, a, u)                  \
00288 ({                                                      \
00289         int c, old;                                     \
00290         c = oro_atomic_read(v);                         \
00291         for (;;) {                                      \
00292                 if (unlikely(c == (u)))                 \
00293                         break;                          \
00294                 old = oro_atomic_oro_cmpxchg((v), c, c + (a));  \
00295                 if (likely(old == c))                   \
00296                         break;                          \
00297                 c = old;                                \
00298         }                                               \
00299         c != (u);                                       \
00300 })
00301 #define oro_atomic_inc_not_zero(v) oro_atomic_add_unless((v), 1, 0)
00302 
00303 #define oro_atomic_sub_and_test(a, v)   (oro_atomic_sub_return((a), (v)) == 0)
00304 #define oro_atomic_dec_and_test(v)              (oro_atomic_dec_return((v)) == 0)
00305 
00306 /*
00307  * Atomically test *v and decrement if it is greater than 0.
00308  * The function returns the old value of *v minus 1.
00309  */
00310 static __inline__ int oro_atomic_dec_if_positive(oro_atomic_t *v)
00311 {
00312   int t;
00313 
00314   __asm__ __volatile__(
00315       LWSYNC_ON_SMP
00316       "1:       lwarx   %0,0,%1         # oro_atomic_dec_if_positive\n\
00317         addic.  %0,%0,-1\n\
00318         blt-    2f\n"
00319       PPC405_ERR77(0,%1)
00320       " stwcx.  %0,0,%1\n\
00321         bne-    1b"
00322       ISYNC_ON_SMP
00323       "\n\
00324 2:" : "=&r" (t)
00325       : "r" (&v->counter)
00326       : "cc", "memory");
00327 
00328   return t;
00329 }
00330 
00331 #define smp_mb__before_oro_atomic_dec()     smp_mb()
00332 #define smp_mb__after_oro_atomic_dec()      smp_mb()
00333 #define smp_mb__before_oro_atomic_inc()     smp_mb()
00334 #define smp_mb__after_oro_atomic_inc()      smp_mb()
00335 
00336 #undef ORO_LOCK
00337 
00338 #ifdef _cplusplus
00339 } // end extern "C"
00340 #endif // _cplusplus
00341 #endif // __ARCH_powerpc_ORO_ATOMIC__


youbot_driver
Author(s): Jan Paulus
autogenerated on Mon Oct 6 2014 09:08:01