00001 /* 00002 * $Id: atomic.h 4518 2008-07-28 15:39:28Z henningw $ 00003 * 00004 * Copyright (C) 2006 kernel.org 00005 * 00006 * This file is part of Kamailio, a free SIP server. 00007 * 00008 * Kamailio is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * Kamailio is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00021 */ 00022 00023 /*! 00024 * \file 00025 * \brief Assembler routines for atomic operations 00026 */ 00027 00028 #ifndef _ATOMIC_OPS_H_ 00029 #define _ATOMIC_OPS_H_ 00030 00031 /************************* i386 & x86_64 ARCH ****************************/ 00032 #if defined(__CPU_i386) || defined(__CPU_x86_64) 00033 00034 #if defined(__SMP_yes) 00035 #define LOCK "lock ; " 00036 #else 00037 #define LOCK "" 00038 #endif 00039 00040 /*! \brief 00041 * Make sure gcc doesn't try to be clever and move things around 00042 * on us. We need to use _exactly_ the address the user gave us, 00043 * not some alias that contains the same information. 00044 */ 00045 typedef struct { volatile unsigned int counter; } atomic_t; 00046 00047 /*! \brief 00048 * atomic_set - set atomic variable 00049 * @v: pointer of type atomic_t 00050 * @i: required value 00051 * 00052 * Atomically sets the value of @v to @i. 00053 */ 00054 #define atomic_set(v,i) (((v)->counter) = (i)) 00055 00056 /*! \brief 00057 * atomic_add - add integer to atomic variable 00058 * @i: integer value to add 00059 * @v: pointer of type atomic_t 00060 * 00061 * Atomically adds @i to @v. 00062 */ 00063 static __inline__ void atomic_add(int i, atomic_t *v) 00064 { 00065 __asm__ __volatile__( 00066 LOCK "addl %1,%0" 00067 :"=m" (v->counter) 00068 :"ir" (i), "m" (v->counter)); 00069 } 00070 00071 /*! \brief 00072 * atomic_sub - subtract the atomic variable 00073 * @i: integer value to subtract 00074 * @v: pointer of type atomic_t 00075 * 00076 * Atomically subtracts @i from @v. 00077 */ 00078 static __inline__ void atomic_sub(int i, atomic_t *v) 00079 { 00080 __asm__ __volatile__( 00081 LOCK "subl %1,%0" 00082 :"=m" (v->counter) 00083 :"ir" (i), "m" (v->counter)); 00084 } 00085 00086 /*! \brief 00087 * atomic_inc - increment atomic variable 00088 * @v: pointer of type atomic_t 00089 * 00090 * Atomically increments @v by 1. 00091 */ 00092 static __inline__ void atomic_inc(atomic_t *v) 00093 { 00094 __asm__ __volatile__( 00095 LOCK "incl %0" 00096 :"=m" (v->counter) 00097 :"m" (v->counter)); 00098 } 00099 00100 /*! \brief 00101 * atomic_dec - decrement atomic variable 00102 * @v: pointer of type atomic_t 00103 * 00104 * Atomically decrements @v by 1. 00105 */ 00106 static __inline__ void atomic_dec(atomic_t *v) 00107 { 00108 __asm__ __volatile__( 00109 LOCK "decl %0" 00110 :"=m" (v->counter) 00111 :"m" (v->counter)); 00112 } 00113 #undef NO_ATOMIC_OPS 00114 00115 /************************* other ARCH ****************************/ 00116 #else 00117 00118 #define NO_ATOMIC_OPS 00119 00120 #endif 00121 00122 #endif
1.5.6