1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
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
|
#ifndef _ALPHA_SPINLOCK_H
#define _ALPHA_SPINLOCK_H
#ifndef __SMP__
/* gcc 2.7.2 can crash initializing an empty structure. */
typedef struct { int dummy; } spinlock_t;
#define SPIN_LOCK_UNLOCKED { 0 }
#define spin_lock_init(lock) do { } while(0)
#define spin_lock(lock) do { } while(0)
#define spin_trylock(lock) do { } while(0)
#define spin_unlock_wait(lock) do { } while(0)
#define spin_unlock(lock) do { } while(0)
#define spin_lock_irq(lock) setipl(7)
#define spin_unlock_irq(lock) setipl(0)
#define spin_lock_irqsave(lock, flags) do { (flags) = swpipl(7); } while (0)
#define spin_unlock_irqrestore(lock, flags) setipl(flags)
/*
* Read-write spinlocks, allowing multiple readers
* but only one writer.
*
* NOTE! it is quite common to have readers in interrupts
* but no interrupt writers. For those circumstances we
* can "mix" irq-safe locks - any writer needs to get a
* irq-safe write-lock, but readers can get non-irqsafe
* read-locks.
*/
typedef struct { int dummy; } rwlock_t;
#define RW_LOCK_UNLOCKED { 0 }
#define read_lock(lock) do { } while(0)
#define read_unlock(lock) do { } while(0)
#define write_lock(lock) do { } while(0)
#define write_unlock(lock) do { } while(0)
#define read_lock_irq(lock) cli()
#define read_unlock_irq(lock) sti()
#define write_lock_irq(lock) cli()
#define write_unlock_irq(lock) sti()
#define read_lock_irqsave(lock, flags) do { (flags) = swpipl(7); } while (0)
#define read_unlock_irqrestore(lock, flags) setipl(flags)
#define write_lock_irqsave(lock, flags) do { (flags) = swpipl(7); } while (0)
#define write_unlock_irqrestore(lock, flags) setipl(flags)
#else
/* Simple spin lock operations. There are two variants, one clears IRQ's
* on the local processor, one does not.
*
* We make no fairness assumptions. They have a cost.
*/
typedef struct {
volatile unsigned long lock;
unsigned long previous;
} spinlock_t;
#define SPIN_LOCK_UNLOCKED { 0, 0 }
#define spin_lock_init(lock) do { (lock)->lock = 0; (lock)->previous = 0; } while(0)
#define spin_unlock_wait(lock) do { barrier(); } while(((volatile spinlock_t *)lock)->lock)
typedef struct { unsigned long a[100]; } __dummy_lock_t;
#define __dummy_lock(lock) (*(__dummy_lock_t *)(lock))
static inline void spin_unlock(spinlock_t * lock)
{
__asm__ __volatile__(
"mb; stq $31,%0"
:"=m" (__dummy_lock(lock)));
}
static inline void spin_lock(spinlock_t * lock)
{
__label__ l1;
long tmp;
long stuck = 0x100000000;
l1:
/* Use sub-sections to put the actual loop at the end
of this object file's text section so as to perfect
branch prediction. */
__asm__ __volatile__(
"1: ldq_l %0,%1\n"
" subq %2,1,%2\n"
" blbs %0,2f\n"
" or %0,1,%0\n"
" stq_c %0,%1\n"
" beq %0,3f\n"
"4: mb\n"
".section .text2,\"ax\"\n"
"2: ldq %0,%1\n"
" subq %2,1,%2\n"
"3: blt %2,4b\n"
" blbs %0,2b\n"
" br 1b\n"
".previous"
: "=r" (tmp),
"=m" (__dummy_lock(lock)),
"=r" (stuck)
: "2" (stuck));
if (stuck < 0)
printk("spinlock stuck at %p (%lx)\n",&&l1,lock->previous);
else
lock->previous = (unsigned long) &&l1;
}
#define spin_trylock(lock) (!test_and_set_bit(0,(lock)))
#define spin_lock_irq(lock) \
do { __cli(); spin_lock(lock); } while (0)
#define spin_unlock_irq(lock) \
do { spin_unlock(lock); __sti(); } while (0)
#define spin_lock_irqsave(lock, flags) \
do { flags = swpipl(7); spin_lock(lock); } while (0)
#define spin_unlock_irqrestore(lock, flags) \
do { spin_unlock(lock); setipl(flags); } while (0)
#endif /* SMP */
#endif /* _ALPHA_SPINLOCK_H */
|