oro_atomic.h

00001 /***************************************************************************
00002   tag: Peter Soetens  Mon Jan 10 15:59:15 CET 2005  oro_atomic.h
00003 
00004                         oro_atomic.h -  description
00005                            -------------------
00006     begin                : Mon January 10 2005
00007     copyright            : (C) 2005 Peter Soetens
00008     email                : peter.soetens@mech.kuleuven.ac.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 
00039 
00040 #include "../../rtt-config.h"
00041 #ifndef __ARCH_x86_64_ORO_ATOMIC__
00042 #define __ARCH_x86_64_ORO_ATOMIC__
00043 
00044 /*
00045  * Atomic operations that C can't guarantee us.  Useful for
00046  * resource counting etc..
00047  */
00048 
00049 #ifndef CONFIG_FORCE_UP
00050 #define ORO_LOCK "lock ; "
00051 #else
00052 #define ORO_LOCK ""
00053 #endif
00054 
00055 /*
00056  * Make sure gcc doesn't try to be clever and move things around
00057  * on us. We need to use _exactly_ the address the user gave us,
00058  * not some alias that contains the same information.
00059  */
00060 typedef struct { volatile int counter; } oro_atomic_t;
00061 
00062 #define ORO_ATOMIC_INIT(i)  { (i) }
00063 #define ORO_ATOMIC_SETUP    oro_atomic_set
00064 #define ORO_ATOMIC_CLEANUP(v)   
00065 
00073 #define oro_atomic_read(v)      ((v)->counter)
00074 
00083 #define oro_atomic_set(v,i)     (((v)->counter) = (i))
00084 
00093 static __inline__ void oro_atomic_add(int i, oro_atomic_t *v)
00094 {
00095     __asm__ __volatile__(
00096         ORO_LOCK "addl %1,%0"
00097         :"=m" (v->counter)
00098         :"ir" (i), "m" (v->counter));
00099 }
00100 
00109 static __inline__ void oro_atomic_sub(int i, oro_atomic_t *v)
00110 {
00111     __asm__ __volatile__(
00112         ORO_LOCK "subl %1,%0"
00113         :"=m" (v->counter)
00114         :"ir" (i), "m" (v->counter));
00115 }
00116 
00127 static __inline__ int oro_atomic_sub_and_test(int i, oro_atomic_t *v)
00128 {
00129     unsigned char c;
00130 
00131     __asm__ __volatile__(
00132         ORO_LOCK "subl %2,%0; sete %1"
00133         :"=m" (v->counter), "=qm" (c)
00134         :"ir" (i), "m" (v->counter) : "memory");
00135     return c;
00136 }
00137 
00145 static __inline__ void oro_atomic_inc(oro_atomic_t *v)
00146 {
00147     __asm__ __volatile__(
00148         ORO_LOCK "incl %0"
00149         :"=m" (v->counter)
00150         :"m" (v->counter));
00151 }
00152 
00160 static __inline__ void oro_atomic_dec(oro_atomic_t *v)
00161 {
00162     __asm__ __volatile__(
00163         ORO_LOCK "decl %0"
00164         :"=m" (v->counter)
00165         :"m" (v->counter));
00166 }
00167 
00177 static __inline__ int oro_atomic_dec_and_test(oro_atomic_t *v)
00178 {
00179     unsigned char c;
00180 
00181     __asm__ __volatile__(
00182         ORO_LOCK "decl %0; sete %1"
00183         :"=m" (v->counter), "=qm" (c)
00184         :"m" (v->counter) : "memory");
00185     return c != 0;
00186 }
00187 
00197 static __inline__ int oro_atomic_inc_and_test(oro_atomic_t *v)
00198 {
00199     unsigned char c;
00200 
00201     __asm__ __volatile__(
00202         ORO_LOCK "incl %0; sete %1"
00203         :"=m" (v->counter), "=qm" (c)
00204         :"m" (v->counter) : "memory");
00205     return c != 0;
00206 }
00207 
00218 static __inline__ int oro_atomic_add_negative(int i, oro_atomic_t *v)
00219 {
00220     unsigned char c;
00221 
00222     __asm__ __volatile__(
00223         ORO_LOCK "addl %2,%0; sets %1"
00224         :"=m" (v->counter), "=qm" (c)
00225         :"ir" (i), "m" (v->counter) : "memory");
00226     return c;
00227 }
00228 
00229 /* An 64bit atomic type */
00230 
00231 typedef struct { volatile long counter; } atomic64_t;
00232 
00233 #define ATOMIC64_INIT(i)    { (i) }
00234 
00242 #define atomic64_read(v)        ((v)->counter)
00243 
00251 #define atomic64_set(v,i)       (((v)->counter) = (i))
00252 
00260 static __inline__ void atomic64_add(long i, atomic64_t *v)
00261 {
00262     __asm__ __volatile__(
00263         ORO_LOCK "addq %1,%0"
00264         :"=m" (v->counter)
00265         :"ir" (i), "m" (v->counter));
00266 }
00267 
00275 static __inline__ void atomic64_sub(long i, atomic64_t *v)
00276 {
00277     __asm__ __volatile__(
00278         ORO_LOCK "subq %1,%0"
00279         :"=m" (v->counter)
00280         :"ir" (i), "m" (v->counter));
00281 }
00282 
00292 static __inline__ int atomic64_sub_and_test(long i, atomic64_t *v)
00293 {
00294     unsigned char c;
00295 
00296     __asm__ __volatile__(
00297         ORO_LOCK "subq %2,%0; sete %1"
00298         :"=m" (v->counter), "=qm" (c)
00299         :"ir" (i), "m" (v->counter) : "memory");
00300     return c;
00301 }
00302 
00309 static __inline__ void atomic64_inc(atomic64_t *v)
00310 {
00311     __asm__ __volatile__(
00312         ORO_LOCK "incq %0"
00313         :"=m" (v->counter)
00314         :"m" (v->counter));
00315 }
00316 
00323 static __inline__ void atomic64_dec(atomic64_t *v)
00324 {
00325     __asm__ __volatile__(
00326         ORO_LOCK "decq %0"
00327         :"=m" (v->counter)
00328         :"m" (v->counter));
00329 }
00330 
00339 static __inline__ int atomic64_dec_and_test(atomic64_t *v)
00340 {
00341     unsigned char c;
00342 
00343     __asm__ __volatile__(
00344         ORO_LOCK "decq %0; sete %1"
00345         :"=m" (v->counter), "=qm" (c)
00346         :"m" (v->counter) : "memory");
00347     return c != 0;
00348 }
00349 
00358 static __inline__ int atomic64_inc_and_test(atomic64_t *v)
00359 {
00360     unsigned char c;
00361 
00362     __asm__ __volatile__(
00363         ORO_LOCK "incq %0; sete %1"
00364         :"=m" (v->counter), "=qm" (c)
00365         :"m" (v->counter) : "memory");
00366     return c != 0;
00367 }
00368 
00378 static __inline__ long atomic64_add_negative(long i, atomic64_t *v)
00379 {
00380     unsigned char c;
00381 
00382     __asm__ __volatile__(
00383         ORO_LOCK "addq %2,%0; sets %1"
00384         :"=m" (v->counter), "=qm" (c)
00385         :"ir" (i), "m" (v->counter) : "memory");
00386     return c;
00387 }
00388 
00396 static __inline__ int oro_atomic_add_return(int i, oro_atomic_t *v)
00397 {
00398     int __i = i;
00399     __asm__ __volatile__(
00400         ORO_LOCK "xaddl %0, %1;"
00401         :"=r"(i)
00402         :"m"(v->counter), "0"(i));
00403     return i + __i;
00404 }
00405 
00406 static __inline__ int oro_atomic_sub_return(int i, oro_atomic_t *v)
00407 {
00408     return oro_atomic_add_return(-i,v);
00409 }
00410 
00411 #define oro_atomic_inc_return(v)  (oro_atomic_add_return(1,v))
00412 #define oro_atomic_dec_return(v)  (oro_atomic_sub_return(1,v))
00413 
00414 /* These are x86-specific, used by some header files */
00415 #define oro_atomic_clear_mask(mask, addr) \
00416 __asm__ __volatile__(ORO_LOCK "andl %0,%1" \
00417 : : "r" (~(mask)),"m" (*addr) : "memory")
00418 
00419 #define oro_atomic_set_mask(mask, addr) \
00420 __asm__ __volatile__(ORO_LOCK "orl %0,%1" \
00421 : : "r" (mask),"m" (*(addr)) : "memory")
00422 
00423 /* Atomic operations are already serializing on x86 */
00424 #define smp_mb__before_oro_atomic_dec() barrier()
00425 #define smp_mb__after_oro_atomic_dec()  barrier()
00426 #define smp_mb__before_oro_atomic_inc() barrier()
00427 #define smp_mb__after_oro_atomic_inc()  barrier()
00428 
00429 #undef ORO_LOCK
00430 #endif
Generated on Thu Dec 23 13:22:38 2010 for Orocos Real-Time Toolkit by  doxygen 1.6.3