1#ifndef __LINUX_SPINLOCK_H
2#define __LINUX_SPINLOCK_H
3
4#include <linux/config.h>
5
6#include <asm/system.h>
7
8/*
9 * These are the generic versions of the spinlocks and read-write
10 * locks..
11 */
12#define spin_lock_irqsave(lock, flags)		do { local_irq_save(flags);       spin_lock(lock); } while (0)
13#define spin_lock_irq(lock)			do { local_irq_disable();         spin_lock(lock); } while (0)
14#define spin_lock_bh(lock)			do { local_bh_disable();          spin_lock(lock); } while (0)
15
16#define read_lock_irqsave(lock, flags)		do { local_irq_save(flags);       read_lock(lock); } while (0)
17#define read_lock_irq(lock)			do { local_irq_disable();         read_lock(lock); } while (0)
18#define read_lock_bh(lock)			do { local_bh_disable();          read_lock(lock); } while (0)
19
20#define write_lock_irqsave(lock, flags)		do { local_irq_save(flags);      write_lock(lock); } while (0)
21#define write_lock_irq(lock)			do { local_irq_disable();        write_lock(lock); } while (0)
22#define write_lock_bh(lock)			do { local_bh_disable();         write_lock(lock); } while (0)
23
24#define spin_unlock_irqrestore(lock, flags)	do { spin_unlock(lock);  local_irq_restore(flags); } while (0)
25#define spin_unlock_irq(lock)			do { spin_unlock(lock);  local_irq_enable();       } while (0)
26#define spin_unlock_bh(lock)			do { spin_unlock(lock);  local_bh_enable();        } while (0)
27
28#define read_unlock_irqrestore(lock, flags)	do { read_unlock(lock);  local_irq_restore(flags); } while (0)
29#define read_unlock_irq(lock)			do { read_unlock(lock);  local_irq_enable();       } while (0)
30#define read_unlock_bh(lock)			do { read_unlock(lock);  local_bh_enable();        } while (0)
31
32#define write_unlock_irqrestore(lock, flags)	do { write_unlock(lock); local_irq_restore(flags); } while (0)
33#define write_unlock_irq(lock)			do { write_unlock(lock); local_irq_enable();       } while (0)
34#define write_unlock_bh(lock)			do { write_unlock(lock); local_bh_enable();        } while (0)
35#define spin_trylock_bh(lock)			({ int __r; local_bh_disable();\
36						__r = spin_trylock(lock);      \
37						if (!__r) local_bh_enable();   \
38						__r; })
39
40/* Must define these before including other files, inline functions need them */
41
42#include <linux/stringify.h>
43
44#define LOCK_SECTION_NAME			\
45	".text.lock." __stringify(KBUILD_BASENAME)
46
47#define LOCK_SECTION_START(extra)		\
48	".subsection 1\n\t"			\
49	extra					\
50	".ifndef " LOCK_SECTION_NAME "\n\t"	\
51	LOCK_SECTION_NAME ":\n\t"		\
52	".endif\n\t"
53
54#define LOCK_SECTION_END			\
55	".previous\n\t"
56
57#ifdef CONFIG_SMP
58#include <asm/spinlock.h>
59
60#elif !defined(spin_lock_init) /* !SMP and spin_lock_init not previously
61                                  defined (e.g. by including asm/spinlock.h */
62
63#define DEBUG_SPINLOCKS	0	/* 0 == no debugging, 1 == maintain lock state, 2 == full debug */
64
65#if (DEBUG_SPINLOCKS < 1)
66
67#define atomic_dec_and_lock(atomic,lock) atomic_dec_and_test(atomic)
68#define ATOMIC_DEC_AND_LOCK
69
70#if (__GNUC__ > 2 || __GNUC_MINOR__ > 95)
71  typedef struct { } spinlock_t;
72  #define SPIN_LOCK_UNLOCKED (spinlock_t) { }
73#else
74  typedef struct { int gcc_is_buggy; } spinlock_t;
75  #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
76#endif
77
78#define spin_lock_init(lock)	do { } while(0)
79#define spin_lock(lock)		(void)(lock) /* Not "unused variable". */
80#define spin_is_locked(lock)	(0)
81#define spin_trylock(lock)	({1; })
82#define spin_unlock_wait(lock)	do { } while(0)
83#define spin_unlock(lock)	do { } while(0)
84
85#elif (DEBUG_SPINLOCKS < 2)
86
87typedef struct {
88	volatile unsigned long lock;
89} spinlock_t;
90#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
91
92#define spin_lock_init(x)	do { (x)->lock = 0; } while (0)
93#define spin_is_locked(lock)	(test_bit(0,(lock)))
94#define spin_trylock(lock)	(!test_and_set_bit(0,(lock)))
95
96#define spin_lock(x)		do { (x)->lock = 1; } while (0)
97#define spin_unlock_wait(x)	do { } while (0)
98#define spin_unlock(x)		do { (x)->lock = 0; } while (0)
99
100#else /* (DEBUG_SPINLOCKS >= 2) */
101
102typedef struct {
103	volatile unsigned long lock;
104	volatile unsigned int babble;
105	const char *module;
106} spinlock_t;
107#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0, 25, __BASE_FILE__ }
108
109#include <linux/kernel.h>
110
111#define spin_lock_init(x)	do { (x)->lock = 0; } while (0)
112#define spin_is_locked(lock)	(test_bit(0,(lock)))
113#define spin_trylock(lock)	(!test_and_set_bit(0,(lock)))
114
115#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)
116#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)
117#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)
118
119#endif	/* DEBUG_SPINLOCKS */
120
121#if (__GNUC__ > 2 || __GNUC_MINOR__ > 91)
122  typedef struct { } rwlock_t;
123  #define RW_LOCK_UNLOCKED (rwlock_t) { }
124#else
125  typedef struct { int gcc_is_buggy; } rwlock_t;
126  #define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
127#endif
128
129#define rwlock_init(lock)	do { } while(0)
130#define read_lock(lock)		(void)(lock) /* Not "unused variable". */
131#define read_unlock(lock)	do { } while(0)
132#define write_lock(lock)	(void)(lock) /* Not "unused variable". */
133#define write_unlock(lock)	do { } while(0)
134
135#endif /* !SMP */
136
137/* "lock on reference count zero" */
138#ifndef ATOMIC_DEC_AND_LOCK
139#include <asm/atomic.h>
140extern int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock);
141#endif
142
143#ifdef CONFIG_SMP
144#include <linux/cache.h>
145
146typedef union {
147    spinlock_t lock;
148    char fill_up[(SMP_CACHE_BYTES)];
149} spinlock_cacheline_t __attribute__ ((aligned(SMP_CACHE_BYTES)));
150
151#else	/* SMP */
152
153typedef struct {
154    spinlock_t lock;
155} spinlock_cacheline_t;
156
157
158#endif
159#endif /* __LINUX_SPINLOCK_H */
160