History

Revert "semaphore: fix"

This reverts commit bf726eab3711cf192405d21688a4b21e07b6188a, as it has been reported to cause a regression with processes stuck in __down(), apparently because some missing wakeup. Quoth Sven Wegener: "I'm currently investigating a regression that has showed up with my last git pull yesterday. Bisecting the commits showed bf726e "semaphore: fix" to be the culprit, reverting it fixed the issue. Symptoms: During heavy filesystem usage (e.g. a kernel compile) I get several compiler processes in uninterruptible sleep, blocking all i/o on the filesystem. System is an Intel Core 2 Quad running a 64bit kernel and userspace. Filesystem is xfs on top of lvm. See below for the output of sysrq-w." See http://lkml.org/lkml/2008/5/10/45 for full report. In the meantime, we can just fix the BKL performance regression by reverting back to the good old BKL spinlock implementation instead, since any sleeping lock will generally perform badly, especially if it tries to be fair.

Linus Torvalds committed 18 years ago

Commit 00b41ec1 parent 39f004b1 file · +34 −30Browse files

Unified · Split

kernel/semaphore.c+34−30
@@ -54,9 +54,10 @@ void down(struct semaphore *sem) · 53 unmodified lines
5454 unsigned long flags;
5555
5656 spin_lock_irqsave(&sem->lock, flags);
57− if (unlikely(!sem->count))
57+ if (likely(sem->count > 0))
58+ sem->count--;
59+ else
5860 __down(sem);
59− sem->count--;
6061 spin_unlock_irqrestore(&sem->lock, flags);
6162 }
6263 EXPORT_SYMBOL(down);
@@ -76,10 +77,10 @@ int down_interruptible(struct semaphore *sem) · 13 unmodified lines
7677 int result = 0;
7778
7879 spin_lock_irqsave(&sem->lock, flags);
79− if (unlikely(!sem->count))
80− result = __down_interruptible(sem);
81− if (!result)
80+ if (likely(sem->count > 0))
8281 sem->count--;
82+ else
83+ result = __down_interruptible(sem);
8384 spin_unlock_irqrestore(&sem->lock, flags);
8485
8586 return result;
@@ -102,10 +103,10 @@ int down_killable(struct semaphore *sem) · 16 unmodified lines
102103 int result = 0;
103104
104105 spin_lock_irqsave(&sem->lock, flags);
105− if (unlikely(!sem->count))
106− result = __down_killable(sem);
107− if (!result)
106+ if (likely(sem->count > 0))
108107 sem->count--;
108+ else
109+ result = __down_killable(sem);
109110 spin_unlock_irqrestore(&sem->lock, flags);
110111
111112 return result;
@@ -156,10 +157,10 @@ int down_timeout(struct semaphore *sem, long jiffies) · 44 unmodified lines
156157 int result = 0;
157158
158159 spin_lock_irqsave(&sem->lock, flags);
159− if (unlikely(!sem->count))
160− result = __down_timeout(sem, jiffies);
161− if (!result)
160+ if (likely(sem->count > 0))
162161 sem->count--;
162+ else
163+ result = __down_timeout(sem, jiffies);
163164 spin_unlock_irqrestore(&sem->lock, flags);
164165
165166 return result;
@@ -178,8 +179,9 @@ void up(struct semaphore *sem) · 12 unmodified lines
178179 unsigned long flags;
179180
180181 spin_lock_irqsave(&sem->lock, flags);
181− sem->count++;
182− if (unlikely(!list_empty(&sem->wait_list)))
182+ if (likely(list_empty(&sem->wait_list)))
183+ sem->count++;
184+ else
183185 __up(sem);
184186 spin_unlock_irqrestore(&sem->lock, flags);
185187 }
@@ -190,6 +192,7 @@ EXPORT_SYMBOL(up); · 4 unmodified lines
190192 struct semaphore_waiter {
191193 struct list_head list;
192194 struct task_struct *task;
195+ int up;
193196 };
194197
195198 /*
@@ -202,34 +205,33 @@ static inline int __sched __down_common(struct semaphore *sem, long state, · 6 unmodified lines
202205 {
203206 struct task_struct *task = current;
204207 struct semaphore_waiter waiter;
205− int ret = 0;
206208
207− waiter.task = task;
208209 list_add_tail(&waiter.list, &sem->wait_list);
210+ waiter.task = task;
211+ waiter.up = 0;
209212
210213 for (;;) {
211− if (state == TASK_INTERRUPTIBLE && signal_pending(task)) {
212− ret = -EINTR;
213− break;
214− }
215− if (state == TASK_KILLABLE && fatal_signal_pending(task)) {
216− ret = -EINTR;
217− break;
218− }
219− if (timeout <= 0) {
220− ret = -ETIME;
221− break;
222− }
214+ if (state == TASK_INTERRUPTIBLE && signal_pending(task))
215+ goto interrupted;
216+ if (state == TASK_KILLABLE && fatal_signal_pending(task))
217+ goto interrupted;
218+ if (timeout <= 0)
219+ goto timed_out;
223220 __set_task_state(task, state);
224221 spin_unlock_irq(&sem->lock);
225222 timeout = schedule_timeout(timeout);
226223 spin_lock_irq(&sem->lock);
227− if (sem->count > 0)
228− break;
224+ if (waiter.up)
225+ return 0;
229226 }
230227
228+ timed_out:
229+ list_del(&waiter.list);
230+ return -ETIME;
231+
232+ interrupted:
231233 list_del(&waiter.list);
232− return ret;
234+ return -EINTR;
233235 }
234236
235237 static noinline void __sched __down(struct semaphore *sem)
@@ -256,5 +258,7 @@ static noinline void __sched __up(struct semaphore *sem) · 20 unmodified lines
256258 {
257259 struct semaphore_waiter *waiter = list_first_entry(&sem->wait_list,
258260 struct semaphore_waiter, list);
261+ list_del(&waiter->list);
262+ waiter->up = 1;
259263 wake_up_process(waiter->task);
260264 }