patch-2.3.1 linux/kernel/sched.c

Next file: linux/kernel/signal.c
Previous file: linux/kernel/printk.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.0/linux/kernel/sched.c linux/kernel/sched.c
@@ -866,52 +866,48 @@
 	return;
 }
 
-rwlock_t waitqueue_lock = RW_LOCK_UNLOCKED;
-
-/*
- * wake_up doesn't wake up stopped processes - they have to be awakened
- * with signals or similar.
- *
- * Note that we only need a read lock for the wait queue (and thus do not
- * have to protect against interrupts), as the actual removal from the
- * queue is handled by the process itself.
- */
-void __wake_up(struct wait_queue **q, unsigned int mode)
+void __wake_up(wait_queue_head_t *q, unsigned int mode)
 {
+	struct list_head *tmp, *head;
 	struct task_struct *p;
-	struct wait_queue *head, *next;
+	unsigned long flags;
 
         if (!q)
 		goto out;
-	/*
-	 * this is safe to be done before the check because it
-	 * means no deference, just pointer operations.
-	 */
-	head = WAIT_QUEUE_HEAD(q);
-
-	read_lock(&waitqueue_lock);
-	next = *q;
-	if (!next)
-		goto out_unlock;
-
-	while (next != head) {
-		p = next->task;
-		next = next->next;
-		if (p->state & mode) {
-			/*
-			 * We can drop the read-lock early if this
-			 * is the only/last process.
-			 */
-			if (next == head) {
-				read_unlock(&waitqueue_lock);
-				wake_up_process(p);
-				goto out;
-			}
+
+	wq_write_lock_irqsave(&q->lock, flags);
+
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC_WQHEAD(q);
+#endif
+
+	head = &q->task_list;
+#if WAITQUEUE_DEBUG
+        if (!head->next || !head->prev)
+                WQ_BUG();
+#endif
+	tmp = head->next;
+	while (tmp != head) {
+		unsigned int state;
+                wait_queue_t *curr = list_entry(tmp, wait_queue_t, task_list);
+
+		tmp = tmp->next;
+
+#if WAITQUEUE_DEBUG
+		CHECK_MAGIC(curr->__magic);
+#endif
+		p = curr->task;
+		state = p->state;
+		if (state & mode) {
+#if WAITQUEUE_DEBUG
+			curr->__waker = (long)__builtin_return_address(0);
+#endif
 			wake_up_process(p);
+			if (state & TASK_EXCLUSIVE)
+				break;
 		}
 	}
-out_unlock:
-	read_unlock(&waitqueue_lock);
+	wq_write_unlock_irqrestore(&q->lock, flags);
 out:
 	return;
 }
@@ -972,7 +968,8 @@
 
 #define DOWN_VAR				\
 	struct task_struct *tsk = current;	\
-	struct wait_queue wait = { tsk, NULL };
+	wait_queue_t wait;			\
+	init_waitqueue_entry(&wait, tsk);
 
 #define DOWN_HEAD(task_state)						\
 									\
@@ -1015,8 +1012,8 @@
 
 int __down_interruptible(struct semaphore * sem)
 {
-	DOWN_VAR
 	int ret = 0;
+	DOWN_VAR
 	DOWN_HEAD(TASK_INTERRUPTIBLE)
 
 	ret = waking_non_zero_interruptible(sem, tsk);
@@ -1039,20 +1036,20 @@
 
 #define	SLEEP_ON_VAR				\
 	unsigned long flags;			\
-	struct wait_queue wait;
+	wait_queue_t wait;			\
+	init_waitqueue_entry(&wait, current);
 
 #define	SLEEP_ON_HEAD					\
-	wait.task = current;				\
-	write_lock_irqsave(&waitqueue_lock,flags);	\
-	__add_wait_queue(p, &wait);			\
-	write_unlock(&waitqueue_lock);
+	wq_write_lock_irqsave(&q->lock,flags);		\
+	__add_wait_queue(q, &wait);			\
+	wq_write_unlock(&q->lock);
 
 #define	SLEEP_ON_TAIL						\
-	write_lock_irq(&waitqueue_lock);			\
-	__remove_wait_queue(p, &wait);				\
-	write_unlock_irqrestore(&waitqueue_lock,flags);
+	wq_write_lock_irq(&q->lock);				\
+	__remove_wait_queue(q, &wait);				\
+	wq_write_unlock_irqrestore(&q->lock,flags);
 
-void interruptible_sleep_on(struct wait_queue **p)
+void interruptible_sleep_on(wait_queue_head_t *q)
 {
 	SLEEP_ON_VAR
 
@@ -1063,7 +1060,7 @@
 	SLEEP_ON_TAIL
 }
 
-long interruptible_sleep_on_timeout(struct wait_queue **p, long timeout)
+long interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout)
 {
 	SLEEP_ON_VAR
 
@@ -1076,7 +1073,7 @@
 	return timeout;
 }
 
-void sleep_on(struct wait_queue **p)
+void sleep_on(wait_queue_head_t *q)
 {
 	SLEEP_ON_VAR
 	
@@ -1087,7 +1084,7 @@
 	SLEEP_ON_TAIL
 }
 
-long sleep_on_timeout(struct wait_queue **p, long timeout)
+long sleep_on_timeout(wait_queue_head_t *q, long timeout)
 {
 	SLEEP_ON_VAR
 	
@@ -1199,8 +1196,8 @@
 	read_lock(&tasklist_lock);
 	for_each_task(p) {
 		if ((p->state == TASK_RUNNING ||
-		     p->state == TASK_UNINTERRUPTIBLE ||
-		     p->state == TASK_SWAPPING))
+		     (p->state & TASK_UNINTERRUPTIBLE) ||
+		     (p->state & TASK_SWAPPING)))
 			nr += FIXED_1;
 	}
 	read_unlock(&tasklist_lock);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)