aboutsummaryrefslogtreecommitdiffstats
path: root/arch/alpha
diff options
context:
space:
mode:
authorMatthew Wilcox <matthew@wil.cx>2008-03-07 21:55:58 -0500
committerMatthew Wilcox <willy@linux.intel.com>2008-04-17 10:42:34 -0400
commit64ac24e738823161693bf791f87adc802cf529ff (patch)
tree19c0b0cf314d4394ca580c05b86cdf874ce0a167 /arch/alpha
parente48b3deee475134585eed03e7afebe4bf9e0dba9 (diff)
Generic semaphore implementation
Semaphores are no longer performance-critical, so a generic C implementation is better for maintainability, debuggability and extensibility. Thanks to Peter Zijlstra for fixing the lockdep warning. Thanks to Harvey Harrison for pointing out that the unlikely() was unnecessary. Signed-off-by: Matthew Wilcox <willy@linux.intel.com> Acked-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/alpha')
-rw-r--r--arch/alpha/kernel/Makefile2
-rw-r--r--arch/alpha/kernel/alpha_ksyms.c9
-rw-r--r--arch/alpha/kernel/semaphore.c224
3 files changed, 1 insertions, 234 deletions
diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile
index dccf05245d4d..ac706c1d7ada 100644
--- a/arch/alpha/kernel/Makefile
+++ b/arch/alpha/kernel/Makefile
@@ -7,7 +7,7 @@ EXTRA_AFLAGS := $(KBUILD_CFLAGS)
7EXTRA_CFLAGS := -Werror -Wno-sign-compare 7EXTRA_CFLAGS := -Werror -Wno-sign-compare
8 8
9obj-y := entry.o traps.o process.o init_task.o osf_sys.o irq.o \ 9obj-y := entry.o traps.o process.o init_task.o osf_sys.o irq.o \
10 irq_alpha.o signal.o setup.o ptrace.o time.o semaphore.o \ 10 irq_alpha.o signal.o setup.o ptrace.o time.o \
11 alpha_ksyms.o systbls.o err_common.o io.o 11 alpha_ksyms.o systbls.o err_common.o io.o
12 12
13obj-$(CONFIG_VGA_HOSE) += console.o 13obj-$(CONFIG_VGA_HOSE) += console.o
diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c
index e9762a33b043..d96e742d4dc2 100644
--- a/arch/alpha/kernel/alpha_ksyms.c
+++ b/arch/alpha/kernel/alpha_ksyms.c
@@ -77,15 +77,6 @@ EXPORT_SYMBOL(__do_clear_user);
77EXPORT_SYMBOL(__strncpy_from_user); 77EXPORT_SYMBOL(__strncpy_from_user);
78EXPORT_SYMBOL(__strnlen_user); 78EXPORT_SYMBOL(__strnlen_user);
79 79
80/* Semaphore helper functions. */
81EXPORT_SYMBOL(__down_failed);
82EXPORT_SYMBOL(__down_failed_interruptible);
83EXPORT_SYMBOL(__up_wakeup);
84EXPORT_SYMBOL(down);
85EXPORT_SYMBOL(down_interruptible);
86EXPORT_SYMBOL(down_trylock);
87EXPORT_SYMBOL(up);
88
89/* 80/*
90 * SMP-specific symbols. 81 * SMP-specific symbols.
91 */ 82 */
diff --git a/arch/alpha/kernel/semaphore.c b/arch/alpha/kernel/semaphore.c
deleted file mode 100644
index 8d2982aa1b8d..000000000000
--- a/arch/alpha/kernel/semaphore.c
+++ /dev/null
@@ -1,224 +0,0 @@
1/*
2 * Alpha semaphore implementation.
3 *
4 * (C) Copyright 1996 Linus Torvalds
5 * (C) Copyright 1999, 2000 Richard Henderson
6 */
7
8#include <linux/errno.h>
9#include <linux/sched.h>
10#include <linux/init.h>
11
12/*
13 * This is basically the PPC semaphore scheme ported to use
14 * the Alpha ll/sc sequences, so see the PPC code for
15 * credits.
16 */
17
18/*
19 * Atomically update sem->count.
20 * This does the equivalent of the following:
21 *
22 * old_count = sem->count;
23 * tmp = MAX(old_count, 0) + incr;
24 * sem->count = tmp;
25 * return old_count;
26 */
27static inline int __sem_update_count(struct semaphore *sem, int incr)
28{
29 long old_count, tmp = 0;
30
31 __asm__ __volatile__(
32 "1: ldl_l %0,%2\n"
33 " cmovgt %0,%0,%1\n"
34 " addl %1,%3,%1\n"
35 " stl_c %1,%2\n"
36 " beq %1,2f\n"
37 " mb\n"
38 ".subsection 2\n"
39 "2: br 1b\n"
40 ".previous"
41 : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
42 : "Ir" (incr), "1" (tmp), "m" (sem->count));
43
44 return old_count;
45}
46
47/*
48 * Perform the "down" function. Return zero for semaphore acquired,
49 * return negative for signalled out of the function.
50 *
51 * If called from down, the return is ignored and the wait loop is
52 * not interruptible. This means that a task waiting on a semaphore
53 * using "down()" cannot be killed until someone does an "up()" on
54 * the semaphore.
55 *
56 * If called from down_interruptible, the return value gets checked
57 * upon return. If the return value is negative then the task continues
58 * with the negative value in the return register (it can be tested by
59 * the caller).
60 *
61 * Either form may be used in conjunction with "up()".
62 */
63
64void __sched
65__down_failed(struct semaphore *sem)
66{
67 struct task_struct *tsk = current;
68 DECLARE_WAITQUEUE(wait, tsk);
69
70#ifdef CONFIG_DEBUG_SEMAPHORE
71 printk("%s(%d): down failed(%p)\n",
72 tsk->comm, task_pid_nr(tsk), sem);
73#endif
74
75 tsk->state = TASK_UNINTERRUPTIBLE;
76 wmb();
77 add_wait_queue_exclusive(&sem->wait, &wait);
78
79 /*
80 * Try to get the semaphore. If the count is > 0, then we've
81 * got the semaphore; we decrement count and exit the loop.
82 * If the count is 0 or negative, we set it to -1, indicating
83 * that we are asleep, and then sleep.
84 */
85 while (__sem_update_count(sem, -1) <= 0) {
86 schedule();
87 set_task_state(tsk, TASK_UNINTERRUPTIBLE);
88 }
89 remove_wait_queue(&sem->wait, &wait);
90 tsk->state = TASK_RUNNING;
91
92 /*
93 * If there are any more sleepers, wake one of them up so
94 * that it can either get the semaphore, or set count to -1
95 * indicating that there are still processes sleeping.
96 */
97 wake_up(&sem->wait);
98
99#ifdef CONFIG_DEBUG_SEMAPHORE
100 printk("%s(%d): down acquired(%p)\n",
101 tsk->comm, task_pid_nr(tsk), sem);
102#endif
103}
104
105int __sched
106__down_failed_interruptible(struct semaphore *sem)
107{
108 struct task_struct *tsk = current;
109 DECLARE_WAITQUEUE(wait, tsk);
110 long ret = 0;
111
112#ifdef CONFIG_DEBUG_SEMAPHORE
113 printk("%s(%d): down failed(%p)\n",
114 tsk->comm, task_pid_nr(tsk), sem);
115#endif
116
117 tsk->state = TASK_INTERRUPTIBLE;
118 wmb();
119 add_wait_queue_exclusive(&sem->wait, &wait);
120
121 while (__sem_update_count(sem, -1) <= 0) {
122 if (signal_pending(current)) {
123 /*
124 * A signal is pending - give up trying.
125 * Set sem->count to 0 if it is negative,
126 * since we are no longer sleeping.
127 */
128 __sem_update_count(sem, 0);
129 ret = -EINTR;
130 break;
131 }
132 schedule();
133 set_task_state(tsk, TASK_INTERRUPTIBLE);
134 }
135
136 remove_wait_queue(&sem->wait, &wait);
137 tsk->state = TASK_RUNNING;
138 wake_up(&sem->wait);
139
140#ifdef CONFIG_DEBUG_SEMAPHORE
141 printk("%s(%d): down %s(%p)\n",
142 current->comm, task_pid_nr(current),
143 (ret < 0 ? "interrupted" : "acquired"), sem);
144#endif
145 return ret;
146}
147
148void
149__up_wakeup(struct semaphore *sem)
150{
151 /*
152 * Note that we incremented count in up() before we came here,
153 * but that was ineffective since the result was <= 0, and
154 * any negative value of count is equivalent to 0.
155 * This ends up setting count to 1, unless count is now > 0
156 * (i.e. because some other cpu has called up() in the meantime),
157 * in which case we just increment count.
158 */
159 __sem_update_count(sem, 1);
160 wake_up(&sem->wait);
161}
162
163void __sched
164down(struct semaphore *sem)
165{
166#ifdef WAITQUEUE_DEBUG
167 CHECK_MAGIC(sem->__magic);
168#endif
169#ifdef CONFIG_DEBUG_SEMAPHORE
170 printk("%s(%d): down(%p) <count=%d> from %p\n",
171 current->comm, task_pid_nr(current), sem,
172 atomic_read(&sem->count), __builtin_return_address(0));
173#endif
174 __down(sem);
175}
176
177int __sched
178down_interruptible(struct semaphore *sem)
179{
180#ifdef WAITQUEUE_DEBUG
181 CHECK_MAGIC(sem->__magic);
182#endif
183#ifdef CONFIG_DEBUG_SEMAPHORE
184 printk("%s(%d): down(%p) <count=%d> from %p\n",
185 current->comm, task_pid_nr(current), sem,
186 atomic_read(&sem->count), __builtin_return_address(0));
187#endif
188 return __down_interruptible(sem);
189}
190
191int
192down_trylock(struct semaphore *sem)
193{
194 int ret;
195
196#ifdef WAITQUEUE_DEBUG
197 CHECK_MAGIC(sem->__magic);
198#endif
199
200 ret = __down_trylock(sem);
201
202#ifdef CONFIG_DEBUG_SEMAPHORE
203 printk("%s(%d): down_trylock %s from %p\n",
204 current->comm, task_pid_nr(current),
205 ret ? "failed" : "acquired",
206 __builtin_return_address(0));
207#endif
208
209 return ret;
210}
211
212void
213up(struct semaphore *sem)
214{
215#ifdef WAITQUEUE_DEBUG
216 CHECK_MAGIC(sem->__magic);
217#endif
218#ifdef CONFIG_DEBUG_SEMAPHORE
219 printk("%s(%d): up(%p) <count=%d> from %p\n",
220 current->comm, task_pid_nr(current), sem,
221 atomic_read(&sem->count), __builtin_return_address(0));
222#endif
223 __up(sem);
224}