spinlock_api_smp.h 5.1 KB
Newer Older
I
Ingo Molnar 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
#ifndef __LINUX_SPINLOCK_API_SMP_H
#define __LINUX_SPINLOCK_API_SMP_H

#ifndef __LINUX_SPINLOCK_H
# error "please don't include this file directly"
#endif

/*
 * include/linux/spinlock_api_smp.h
 *
 * spinlock API declarations on SMP (and debug)
 * (implemented in kernel/spinlock.c)
 *
 * portions Copyright 2005, Red Hat, Inc., Ingo Molnar
 * Released under the General Public License (GPL).
 */

int in_lock_functions(unsigned long addr);

#define assert_spin_locked(x)	BUG_ON(!spin_is_locked(x))

22
void __lockfunc _spin_lock(spinlock_t *lock)		__acquires(lock);
23
void __lockfunc _spin_lock_nested(spinlock_t *lock, int subclass)
24
							__acquires(lock);
P
Peter Zijlstra 已提交
25 26
void __lockfunc _spin_lock_nest_lock(spinlock_t *lock, struct lockdep_map *map)
							__acquires(lock);
27 28
void __lockfunc _spin_lock_bh(spinlock_t *lock)		__acquires(lock);
void __lockfunc _spin_lock_irq(spinlock_t *lock)	__acquires(lock);
29

I
Ingo Molnar 已提交
30
unsigned long __lockfunc _spin_lock_irqsave(spinlock_t *lock)
31
							__acquires(lock);
32 33
unsigned long __lockfunc _spin_lock_irqsave_nested(spinlock_t *lock, int subclass)
							__acquires(lock);
I
Ingo Molnar 已提交
34 35
int __lockfunc _spin_trylock(spinlock_t *lock);
int __lockfunc _spin_trylock_bh(spinlock_t *lock);
36 37 38
void __lockfunc _spin_unlock(spinlock_t *lock)		__releases(lock);
void __lockfunc _spin_unlock_bh(spinlock_t *lock)	__releases(lock);
void __lockfunc _spin_unlock_irq(spinlock_t *lock)	__releases(lock);
I
Ingo Molnar 已提交
39
void __lockfunc _spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)
40
							__releases(lock);
I
Ingo Molnar 已提交
41

42
#ifdef CONFIG_INLINE_SPIN_LOCK
43 44 45
#define _spin_lock(lock) __spin_lock(lock)
#endif

46
#ifdef CONFIG_INLINE_SPIN_LOCK_BH
47 48 49
#define _spin_lock_bh(lock) __spin_lock_bh(lock)
#endif

50
#ifdef CONFIG_INLINE_SPIN_LOCK_IRQ
51 52 53
#define _spin_lock_irq(lock) __spin_lock_irq(lock)
#endif

54
#ifdef CONFIG_INLINE_SPIN_LOCK_IRQSAVE
55 56 57
#define _spin_lock_irqsave(lock) __spin_lock_irqsave(lock)
#endif

58
#ifdef CONFIG_INLINE_SPIN_TRYLOCK
59 60 61
#define _spin_trylock(lock) __spin_trylock(lock)
#endif

62
#ifdef CONFIG_INLINE_SPIN_TRYLOCK_BH
63 64 65
#define _spin_trylock_bh(lock) __spin_trylock_bh(lock)
#endif

66
#ifdef CONFIG_INLINE_SPIN_UNLOCK
67 68 69
#define _spin_unlock(lock) __spin_unlock(lock)
#endif

70
#ifdef CONFIG_INLINE_SPIN_UNLOCK_BH
71 72 73
#define _spin_unlock_bh(lock) __spin_unlock_bh(lock)
#endif

74
#ifdef CONFIG_INLINE_SPIN_UNLOCK_IRQ
75 76 77
#define _spin_unlock_irq(lock) __spin_unlock_irq(lock)
#endif

78
#ifdef CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE
79 80 81
#define _spin_unlock_irqrestore(lock, flags) __spin_unlock_irqrestore(lock, flags)
#endif

82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
static inline int __spin_trylock(spinlock_t *lock)
{
	preempt_disable();
	if (_raw_spin_trylock(lock)) {
		spin_acquire(&lock->dep_map, 0, 1, _RET_IP_);
		return 1;
	}
	preempt_enable();
	return 0;
}

/*
 * If lockdep is enabled then we use the non-preemption spin-ops
 * even on CONFIG_PREEMPT, because lockdep assumes that interrupts are
 * not re-enabled during lock-acquire (which the preempt-spin-ops do):
 */
#if !defined(CONFIG_GENERIC_LOCKBREAK) || defined(CONFIG_DEBUG_LOCK_ALLOC)

static inline unsigned long __spin_lock_irqsave(spinlock_t *lock)
{
	unsigned long flags;

	local_irq_save(flags);
	preempt_disable();
	spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
	/*
	 * On lockdep we dont want the hand-coded irq-enable of
	 * _raw_spin_lock_flags() code, because lockdep assumes
	 * that interrupts are not re-enabled during lock-acquire:
	 */
#ifdef CONFIG_LOCKDEP
	LOCK_CONTENDED(lock, _raw_spin_trylock, _raw_spin_lock);
#else
	_raw_spin_lock_flags(lock, &flags);
#endif
	return flags;
}

static inline void __spin_lock_irq(spinlock_t *lock)
{
	local_irq_disable();
	preempt_disable();
	spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
	LOCK_CONTENDED(lock, _raw_spin_trylock, _raw_spin_lock);
}

static inline void __spin_lock_bh(spinlock_t *lock)
{
	local_bh_disable();
	preempt_disable();
	spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
	LOCK_CONTENDED(lock, _raw_spin_trylock, _raw_spin_lock);
}

static inline void __spin_lock(spinlock_t *lock)
{
	preempt_disable();
	spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
	LOCK_CONTENDED(lock, _raw_spin_trylock, _raw_spin_lock);
}

#endif /* CONFIG_PREEMPT */

static inline void __spin_unlock(spinlock_t *lock)
{
	spin_release(&lock->dep_map, 1, _RET_IP_);
	_raw_spin_unlock(lock);
	preempt_enable();
}

static inline void __spin_unlock_irqrestore(spinlock_t *lock,
					    unsigned long flags)
{
	spin_release(&lock->dep_map, 1, _RET_IP_);
	_raw_spin_unlock(lock);
	local_irq_restore(flags);
	preempt_enable();
}

static inline void __spin_unlock_irq(spinlock_t *lock)
{
	spin_release(&lock->dep_map, 1, _RET_IP_);
	_raw_spin_unlock(lock);
	local_irq_enable();
	preempt_enable();
}

static inline void __spin_unlock_bh(spinlock_t *lock)
{
	spin_release(&lock->dep_map, 1, _RET_IP_);
	_raw_spin_unlock(lock);
	preempt_enable_no_resched();
	local_bh_enable_ip((unsigned long)__builtin_return_address(0));
}

static inline int __spin_trylock_bh(spinlock_t *lock)
{
	local_bh_disable();
	preempt_disable();
	if (_raw_spin_trylock(lock)) {
		spin_acquire(&lock->dep_map, 0, 1, _RET_IP_);
		return 1;
	}
	preempt_enable_no_resched();
	local_bh_enable_ip((unsigned long)__builtin_return_address(0));
	return 0;
}

190 191
#include <linux/rwlock_api_smp.h>

I
Ingo Molnar 已提交
192
#endif /* __LINUX_SPINLOCK_API_SMP_H */