|
|
1.1 root 1: #ifndef __ASM_SPINLOCK_H
2: #define __ASM_SPINLOCK_H
3:
4: #ifndef __SMP__
5:
6: #define DEBUG_SPINLOCKS 0 /* 0 == no debugging, 1 == maintain lock state, 2 == full debug */
7:
8: #if (DEBUG_SPINLOCKS < 1)
9:
10: /*
11: * Your basic spinlocks, allowing only a single CPU anywhere
12: *
13: * Gcc-2.7.x has a nasty bug with empty initializers.
14: */
15: #if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8)
16: typedef struct { } spinlock_t;
17: #define SPIN_LOCK_UNLOCKED (spinlock_t) { }
18: #else
19: typedef struct { int gcc_is_buggy; } spinlock_t;
20: #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
21: #endif
22:
23: #define spin_lock_init(lock) do { } while(0)
24: #define spin_lock(lock) (void)(lock) /* Not "unused variable". */
25: #define spin_trylock(lock) (1)
26: #define spin_unlock_wait(lock) do { } while(0)
27: #define spin_unlock(lock) do { } while(0)
28: #define spin_lock_irq(lock) cli()
29: #define spin_unlock_irq(lock) sti()
30:
31: #define spin_lock_irqsave(lock, flags) \
32: do { save_flags(flags); cli(); } while (0)
33: #define spin_unlock_irqrestore(lock, flags) \
34: restore_flags(flags)
35:
36: #elif (DEBUG_SPINLOCKS < 2)
37:
38: typedef struct {
39: volatile unsigned int lock;
40: } spinlock_t;
41: #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
42:
43: #define spin_lock_init(x) do { (x)->lock = 0; } while (0)
44: #define spin_trylock(lock) (!test_and_set_bit(0,(lock)))
45:
46: #define spin_lock(x) do { (x)->lock = 1; } while (0)
47: #define spin_unlock_wait(x) do { } while (0)
48: #define spin_unlock(x) do { (x)->lock = 0; } while (0)
49: #define spin_lock_irq(x) do { cli(); spin_lock(x); } while (0)
50: #define spin_unlock_irq(x) do { spin_unlock(x); sti(); } while (0)
51:
52: #define spin_lock_irqsave(x, flags) \
53: do { save_flags(flags); spin_lock_irq(x); } while (0)
54: #define spin_unlock_irqrestore(x, flags) \
55: do { spin_unlock(x); restore_flags(flags); } while (0)
56:
57: #else /* (DEBUG_SPINLOCKS >= 2) */
58:
59: typedef struct {
60: volatile unsigned int lock;
61: volatile unsigned int babble;
62: const char *module;
63: } spinlock_t;
64: #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0, 25, __BASE_FILE__ }
65:
66: #include <linux/kernel.h>
67:
68: #define spin_lock_init(x) do { (x)->lock = 0; } while (0)
69: #define spin_trylock(lock) (!test_and_set_bit(0,(lock)))
70:
71: #define spin_lock(x) do {unsigned long __spinflags; save_flags(__spinflags); cli(); if ((x)->lock&&(x)->babble) {printk("%s:%d: spin_lock(%s:%p) already locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 1; restore_flags(__spinflags);} while (0)
72: #define spin_unlock_wait(x) do {unsigned long __spinflags; save_flags(__spinflags); cli(); if ((x)->lock&&(x)->babble) {printk("%s:%d: spin_unlock_wait(%s:%p) deadlock\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} restore_flags(__spinflags);} while (0)
73: #define spin_unlock(x) do {unsigned long __spinflags; save_flags(__spinflags); cli(); if (!(x)->lock&&(x)->babble) {printk("%s:%d: spin_unlock(%s:%p) not locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 0; restore_flags(__spinflags);} while (0)
74: #define spin_lock_irq(x) do {cli(); if ((x)->lock&&(x)->babble) {printk("%s:%d: spin_lock_irq(%s:%p) already locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 1;} while (0)
75: #define spin_unlock_irq(x) do {cli(); if (!(x)->lock&&(x)->babble) {printk("%s:%d: spin_unlock_irq(%s:%p) not locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 0; sti();} while (0)
76:
77: #define spin_lock_irqsave(x,flags) do {save_flags(flags); cli(); if ((x)->lock&&(x)->babble) {printk("%s:%d: spin_lock_irqsave(%s:%p) already locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 1;} while (0)
78: #define spin_unlock_irqrestore(x,flags) do {cli(); if (!(x)->lock&&(x)->babble) {printk("%s:%d: spin_unlock_irqrestore(%s:%p) not locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 0; restore_flags(flags);} while (0)
79:
80: #endif /* DEBUG_SPINLOCKS */
81:
82: /*
83: * Read-write spinlocks, allowing multiple readers
84: * but only one writer.
85: *
86: * NOTE! it is quite common to have readers in interrupts
87: * but no interrupt writers. For those circumstances we
88: * can "mix" irq-safe locks - any writer needs to get a
89: * irq-safe write-lock, but readers can get non-irqsafe
90: * read-locks.
91: *
92: * Gcc-2.7.x has a nasty bug with empty initializers.
93: */
94: #if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8)
95: typedef struct { } rwlock_t;
96: #define RW_LOCK_UNLOCKED (rwlock_t) { }
97: #else
98: typedef struct { int gcc_is_buggy; } rwlock_t;
99: #define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
100: #endif
101:
102: #define read_lock(lock) (void)(lock) /* Not "unused variable." */
103: #define read_unlock(lock) do { } while(0)
104: #define write_lock(lock) (void)(lock) /* Not "unused variable." */
105: #define write_unlock(lock) do { } while(0)
106: #define read_lock_irq(lock) cli()
107: #define read_unlock_irq(lock) sti()
108: #define write_lock_irq(lock) cli()
109: #define write_unlock_irq(lock) sti()
110:
111: #define read_lock_irqsave(lock, flags) \
112: do { save_flags(flags); cli(); } while (0)
113: #define read_unlock_irqrestore(lock, flags) \
114: restore_flags(flags)
115: #define write_lock_irqsave(lock, flags) \
116: do { save_flags(flags); cli(); } while (0)
117: #define write_unlock_irqrestore(lock, flags) \
118: restore_flags(flags)
119:
120: #else /* __SMP__ */
121:
122: /*
123: * Your basic spinlocks, allowing only a single CPU anywhere
124: */
125:
126: typedef struct {
127: volatile unsigned int lock;
128: } spinlock_t;
129:
130: #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
131:
132: #define spin_lock_init(x) do { (x)->lock = 0; } while(0)
133: /*
134: * Simple spin lock operations. There are two variants, one clears IRQ's
135: * on the local processor, one does not.
136: *
137: * We make no fairness assumptions. They have a cost.
138: */
139:
140: #define spin_unlock_wait(x) do { barrier(); } while(((volatile spinlock_t *)(x))->lock)
141:
142: typedef struct { unsigned long a[100]; } __dummy_lock_t;
143: #define __dummy_lock(lock) (*(__dummy_lock_t *)(lock))
144:
145: /*
146: * Intel PIV would benefit from using 'rep nop' here but on older
147: * processors and non intel it is listed as 'undefined' so cannot be
148: * blindly used. On 2.4 we should add a PIV CPU type for this one.
149: */
150: #define spin_lock_string \
151: "\n1:\t" \
152: "lock ; btsl $0,%0\n\t" \
153: "jc 2f\n" \
154: ".section .text.lock,\"ax\"\n" \
155: "2:\t" \
156: "rep; nop\n\t" \
157: "testb $1,%0\n\t" \
158: "jne 2b\n\t" \
159: "jmp 1b\n" \
160: ".previous"
161:
162: #define spin_unlock_string \
163: "lock ; btrl $0,%0"
164:
165: #define spin_lock(lock) \
166: __asm__ __volatile__( \
167: spin_lock_string \
168: :"=m" (__dummy_lock(lock)))
169:
170: #define spin_unlock(lock) \
171: __asm__ __volatile__( \
172: spin_unlock_string \
173: :"=m" (__dummy_lock(lock)))
174:
175: #define spin_trylock(lock) (!test_and_set_bit(0,(lock)))
176:
177: #define spin_lock_irq(lock) \
178: do { __cli(); spin_lock(lock); } while (0)
179:
180: #define spin_unlock_irq(lock) \
181: do { spin_unlock(lock); __sti(); } while (0)
182:
183: #define spin_lock_irqsave(lock, flags) \
184: do { __save_flags(flags); __cli(); spin_lock(lock); } while (0)
185:
186: #define spin_unlock_irqrestore(lock, flags) \
187: do { spin_unlock(lock); __restore_flags(flags); } while (0)
188:
189: /*
190: * Read-write spinlocks, allowing multiple readers
191: * but only one writer.
192: *
193: * NOTE! it is quite common to have readers in interrupts
194: * but no interrupt writers. For those circumstances we
195: * can "mix" irq-safe locks - any writer needs to get a
196: * irq-safe write-lock, but readers can get non-irqsafe
197: * read-locks.
198: */
199: typedef struct {
200: volatile unsigned int lock;
201: unsigned long previous;
202: } rwlock_t;
203:
204: #define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 }
205:
206: /*
207: * On x86, we implement read-write locks as a 32-bit counter
208: * with the high bit (sign) being the "write" bit.
209: *
210: * The inline assembly is non-obvious. Think about it.
211: */
212: #define read_lock(rw) \
213: asm volatile("\n1:\t" \
214: "lock ; incl %0\n\t" \
215: "js 2f\n" \
216: ".section .text.lock,\"ax\"\n" \
217: "2:\tlock ; decl %0\n" \
218: "3:\trep; nop\n\t" \
219: "cmpl $0,%0\n\t" \
220: "js 3b\n\t" \
221: "jmp 1b\n" \
222: ".previous" \
223: :"=m" (__dummy_lock(&(rw)->lock)))
224:
225: #define read_unlock(rw) \
226: asm volatile("lock ; decl %0" \
227: :"=m" (__dummy_lock(&(rw)->lock)))
228:
229: #define write_lock(rw) \
230: asm volatile("\n1:\t" \
231: "lock ; btsl $31,%0\n\t" \
232: "jc 4f\n" \
233: "2:\ttestl $0x7fffffff,%0\n\t" \
234: "jne 3f\n" \
235: ".section .text.lock,\"ax\"\n" \
236: "3:\tlock ; btrl $31,%0\n" \
237: "4:\trep; nop\n\t" \
238: "cmp $0,%0\n\t" \
239: "jne 4b\n\t" \
240: "jmp 1b\n" \
241: ".previous" \
242: :"=m" (__dummy_lock(&(rw)->lock)))
243:
244: #define write_unlock(rw) \
245: asm volatile("lock ; btrl $31,%0":"=m" (__dummy_lock(&(rw)->lock)))
246:
247: #define read_lock_irq(lock) do { __cli(); read_lock(lock); } while (0)
248: #define read_unlock_irq(lock) do { read_unlock(lock); __sti(); } while (0)
249: #define write_lock_irq(lock) do { __cli(); write_lock(lock); } while (0)
250: #define write_unlock_irq(lock) do { write_unlock(lock); __sti(); } while (0)
251:
252: #define read_lock_irqsave(lock, flags) \
253: do { __save_flags(flags); __cli(); read_lock(lock); } while (0)
254: #define read_unlock_irqrestore(lock, flags) \
255: do { read_unlock(lock); __restore_flags(flags); } while (0)
256: #define write_lock_irqsave(lock, flags) \
257: do { __save_flags(flags); __cli(); write_lock(lock); } while (0)
258: #define write_unlock_irqrestore(lock, flags) \
259: do { write_unlock(lock); __restore_flags(flags); } while (0)
260:
261: #endif /* __SMP__ */
262: #endif /* __ASM_SPINLOCK_H */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.