~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/include/asm-mips/atomic.h

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * Atomic operations that C can't guarantee us.  Useful for
  3  * resource counting etc..
  4  *
  5  * But use these as seldom as possible since they are much more slower
  6  * than regular operations.
  7  *
  8  * This file is subject to the terms and conditions of the GNU General Public
  9  * License.  See the file "COPYING" in the main directory of this archive
 10  * for more details.
 11  *
 12  * Copyright (C) 1996, 1997 by Ralf Baechle
 13  *
 14  * $Id: atomic.h,v 1.6 1999/07/26 19:42:42 harald Exp $
 15  */
 16 #ifndef __ASM_ATOMIC_H
 17 #define __ASM_ATOMIC_H
 18 
 19 #include <linux/config.h>
 20 
 21 #ifdef CONFIG_SMP
 22 typedef struct { volatile int counter; } atomic_t;
 23 #else
 24 typedef struct { int counter; } atomic_t;
 25 #endif
 26 
 27 #ifdef __KERNEL__
 28 #define ATOMIC_INIT(i)    { (i) }
 29 
 30 #define atomic_read(v)  ((v)->counter)
 31 #define atomic_set(v,i) ((v)->counter = (i))
 32 
 33 #if !defined(CONFIG_CPU_HAS_LLSC)
 34 
 35 #include <asm/system.h>
 36 
 37 /*
 38  * The MIPS I implementation is only atomic with respect to
 39  * interrupts.  R3000 based multiprocessor machines are rare anyway ...
 40  */
 41 extern __inline__ void atomic_add(int i, volatile atomic_t * v)
 42 {
 43         int     flags;
 44 
 45         save_flags(flags);
 46         cli();
 47         v->counter += i;
 48         restore_flags(flags);
 49 }
 50 
 51 extern __inline__ void atomic_sub(int i, volatile atomic_t * v)
 52 {
 53         int     flags;
 54 
 55         save_flags(flags);
 56         cli();
 57         v->counter -= i;
 58         restore_flags(flags);
 59 }
 60 
 61 extern __inline__ int atomic_add_return(int i, atomic_t * v)
 62 {
 63         int     temp, flags;
 64 
 65         save_flags(flags);
 66         cli();
 67         temp = v->counter;
 68         temp += i;
 69         v->counter = temp;
 70         restore_flags(flags);
 71 
 72         return temp;
 73 }
 74 
 75 extern __inline__ int atomic_sub_return(int i, atomic_t * v)
 76 {
 77         int     temp, flags;
 78 
 79         save_flags(flags);
 80         cli();
 81         temp = v->counter;
 82         temp -= i;
 83         v->counter = temp;
 84         restore_flags(flags);
 85 
 86         return temp;
 87 }
 88 
 89 extern __inline__ void atomic_clear_mask(unsigned long mask, unsigned long * v)
 90 {
 91         unsigned long temp;
 92         int     flags;
 93 
 94         save_flags(flags);
 95         cli();
 96         temp = *v;
 97         temp &= ~mask;
 98         *v = temp;
 99         restore_flags(flags);
100 
101         return;
102 }
103 
104 #else
105 
106 /*
107  * ... while for MIPS II and better we can use ll/sc instruction.  This
108  * implementation is SMP safe ...
109  */
110 
111 /*
112  * Make sure gcc doesn't try to be clever and move things around
113  * on us. We need to use _exactly_ the address the user gave us,
114  * not some alias that contains the same information.
115  */
116 #define __atomic_fool_gcc(x) (*(volatile struct { int a[100]; } *)x)
117 
118 extern __inline__ void atomic_add(int i, volatile atomic_t * v)
119 {
120         unsigned long temp;
121 
122         __asm__ __volatile__(
123                 "1:\tll\t%0,%1\n\t"
124                 "addu\t%0,%2\n\t"
125                 "sc\t%0,%1\n\t"
126                 "beqz\t%0,1b"
127                 :"=&r" (temp),
128                  "=m" (__atomic_fool_gcc(v))
129                 :"Ir" (i),
130                  "m" (__atomic_fool_gcc(v)));
131 }
132 
133 extern __inline__ void atomic_sub(int i, volatile atomic_t * v)
134 {
135         unsigned long temp;
136 
137         __asm__ __volatile__(
138                 "1:\tll\t%0,%1\n\t"
139                 "subu\t%0,%2\n\t"
140                 "sc\t%0,%1\n\t"
141                 "beqz\t%0,1b"
142                 :"=&r" (temp),
143                  "=m" (__atomic_fool_gcc(v))
144                 :"Ir" (i),
145                  "m" (__atomic_fool_gcc(v)));
146 }
147 
148 /*
149  * Same as above, but return the result value
150  */
151 extern __inline__ int atomic_add_return(int i, atomic_t * v)
152 {
153         unsigned long temp, result;
154 
155         __asm__ __volatile__(
156                 ".set\tnoreorder\n"
157                 "1:\tll\t%1,%2\n\t"
158                 "addu\t%0,%1,%3\n\t"
159                 "sc\t%0,%2\n\t"
160                 "beqz\t%0,1b\n\t"
161                 "addu\t%0,%1,%3\n\t"
162                 ".set\treorder"
163                 :"=&r" (result),
164                  "=&r" (temp),
165                  "=m" (__atomic_fool_gcc(v))
166                 :"Ir" (i),
167                  "m" (__atomic_fool_gcc(v)));
168 
169         return result;
170 }
171 
172 extern __inline__ int atomic_sub_return(int i, atomic_t * v)
173 {
174         unsigned long temp, result;
175 
176         __asm__ __volatile__(
177                 ".set\tnoreorder\n"
178                 "1:\tll\t%1,%2\n\t"
179                 "subu\t%0,%1,%3\n\t"
180                 "sc\t%0,%2\n\t"
181                 "beqz\t%0,1b\n\t"
182                 "subu\t%0,%1,%3\n\t"
183                 ".set\treorder"
184                 :"=&r" (result),
185                  "=&r" (temp),
186                  "=m" (__atomic_fool_gcc(v))
187                 :"Ir" (i),
188                  "m" (__atomic_fool_gcc(v)));
189 
190         return result;
191 }
192 #endif
193 
194 #define atomic_dec_return(v) atomic_sub_return(1,(v))
195 #define atomic_inc_return(v) atomic_add_return(1,(v))
196 
197 #define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
198 #define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
199 
200 #define atomic_inc(v) atomic_add(1,(v))
201 #define atomic_dec(v) atomic_sub(1,(v))
202 #endif /* defined(__KERNEL__) */
203 
204 #endif /* __ASM_MIPS_ATOMIC_H */
205 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.