1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#include <linux/config.h>
16#include <linux/sched.h>
17#include <asm/semaphore.h>
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
50void __up(struct semaphore *sem)
51{
52 wake_up(&sem->wait);
53}
54
55static spinlock_t semaphore_lock = SPIN_LOCK_UNLOCKED;
56
57void __down(struct semaphore * sem)
58{
59 struct task_struct *tsk = current;
60 DECLARE_WAITQUEUE(wait, tsk);
61 tsk->state = TASK_UNINTERRUPTIBLE;
62 add_wait_queue_exclusive(&sem->wait, &wait);
63
64 spin_lock_irq(&semaphore_lock);
65 sem->sleepers++;
66 for (;;) {
67 int sleepers = sem->sleepers;
68
69
70
71
72
73 if (!atomic_add_negative(sleepers - 1, &sem->count)) {
74 sem->sleepers = 0;
75 break;
76 }
77 sem->sleepers = 1;
78 spin_unlock_irq(&semaphore_lock);
79
80 schedule();
81 tsk->state = TASK_UNINTERRUPTIBLE;
82 spin_lock_irq(&semaphore_lock);
83 }
84 spin_unlock_irq(&semaphore_lock);
85 remove_wait_queue(&sem->wait, &wait);
86 tsk->state = TASK_RUNNING;
87 wake_up(&sem->wait);
88}
89
90int __down_interruptible(struct semaphore * sem)
91{
92 int retval = 0;
93 struct task_struct *tsk = current;
94 DECLARE_WAITQUEUE(wait, tsk);
95 tsk->state = TASK_INTERRUPTIBLE;
96 add_wait_queue_exclusive(&sem->wait, &wait);
97
98 spin_lock_irq(&semaphore_lock);
99 sem->sleepers ++;
100 for (;;) {
101 int sleepers = sem->sleepers;
102
103
104
105
106
107
108
109
110 if (signal_pending(current)) {
111 retval = -EINTR;
112 sem->sleepers = 0;
113 atomic_add(sleepers, &sem->count);
114 break;
115 }
116
117
118
119
120
121
122
123 if (!atomic_add_negative(sleepers - 1, &sem->count)) {
124 sem->sleepers = 0;
125 break;
126 }
127 sem->sleepers = 1;
128 spin_unlock_irq(&semaphore_lock);
129
130 schedule();
131 tsk->state = TASK_INTERRUPTIBLE;
132 spin_lock_irq(&semaphore_lock);
133 }
134 spin_unlock_irq(&semaphore_lock);
135 tsk->state = TASK_RUNNING;
136 remove_wait_queue(&sem->wait, &wait);
137 wake_up(&sem->wait);
138 return retval;
139}
140
141
142
143
144
145
146
147
148
149int __down_trylock(struct semaphore * sem)
150{
151 int sleepers;
152 unsigned long flags;
153
154 spin_lock_irqsave(&semaphore_lock, flags);
155 sleepers = sem->sleepers + 1;
156 sem->sleepers = 0;
157
158
159
160
161
162 if (!atomic_add_negative(sleepers, &sem->count))
163 wake_up(&sem->wait);
164
165 spin_unlock_irqrestore(&semaphore_lock, flags);
166 return 1;
167}
168
169
170
171
172
173
174
175
176
177
178
179
180asm(
181".text\n"
182".align 4\n"
183".globl __down_failed\n"
184"__down_failed:\n\t"
185#if defined(CONFIG_FRAME_POINTER)
186 "pushl %ebp\n\t"
187 "movl %esp,%ebp\n\t"
188#endif
189 "pushl %eax\n\t"
190 "pushl %edx\n\t"
191 "pushl %ecx\n\t"
192 "call __down\n\t"
193 "popl %ecx\n\t"
194 "popl %edx\n\t"
195 "popl %eax\n\t"
196#if defined(CONFIG_FRAME_POINTER)
197 "movl %ebp,%esp\n\t"
198 "popl %ebp\n\t"
199#endif
200 "ret"
201);
202
203asm(
204".text\n"
205".align 4\n"
206".globl __down_failed_interruptible\n"
207"__down_failed_interruptible:\n\t"
208#if defined(CONFIG_FRAME_POINTER)
209 "pushl %ebp\n\t"
210 "movl %esp,%ebp\n\t"
211#endif
212 "pushl %edx\n\t"
213 "pushl %ecx\n\t"
214 "call __down_interruptible\n\t"
215 "popl %ecx\n\t"
216 "popl %edx\n\t"
217#if defined(CONFIG_FRAME_POINTER)
218 "movl %ebp,%esp\n\t"
219 "popl %ebp\n\t"
220#endif
221 "ret"
222);
223
224asm(
225".text\n"
226".align 4\n"
227".globl __down_failed_trylock\n"
228"__down_failed_trylock:\n\t"
229#if defined(CONFIG_FRAME_POINTER)
230 "pushl %ebp\n\t"
231 "movl %esp,%ebp\n\t"
232#endif
233 "pushl %edx\n\t"
234 "pushl %ecx\n\t"
235 "call __down_trylock\n\t"
236 "popl %ecx\n\t"
237 "popl %edx\n\t"
238#if defined(CONFIG_FRAME_POINTER)
239 "movl %ebp,%esp\n\t"
240 "popl %ebp\n\t"
241#endif
242 "ret"
243);
244
245asm(
246".text\n"
247".align 4\n"
248".globl __up_wakeup\n"
249"__up_wakeup:\n\t"
250 "pushl %eax\n\t"
251 "pushl %edx\n\t"
252 "pushl %ecx\n\t"
253 "call __up\n\t"
254 "popl %ecx\n\t"
255 "popl %edx\n\t"
256 "popl %eax\n\t"
257 "ret"
258);
259
260
261
262
263#if defined(CONFIG_SMP)
264asm(
265".text\n"
266".align 4\n"
267".globl __write_lock_failed\n"
268"__write_lock_failed:\n\t"
269 LOCK "addl $" RW_LOCK_BIAS_STR ",(%eax)\n"
270"1: rep; nop\n\t"
271 "cmpl $" RW_LOCK_BIAS_STR ",(%eax)\n\t"
272 "jne 1b\n\t"
273 LOCK "subl $" RW_LOCK_BIAS_STR ",(%eax)\n\t"
274 "jnz __write_lock_failed\n\t"
275 "ret"
276);
277
278asm(
279".text\n"
280".align 4\n"
281".globl __read_lock_failed\n"
282"__read_lock_failed:\n\t"
283 LOCK "incl (%eax)\n"
284"1: rep; nop\n\t"
285 "cmpl $1,(%eax)\n\t"
286 "js 1b\n\t"
287 LOCK "decl (%eax)\n\t"
288 "js __read_lock_failed\n\t"
289 "ret"
290);
291#endif
292