diff -urN 2.2.19pre2/include/linux/sched.h wakeone/include/linux/sched.h
--- 2.2.19pre2/include/linux/sched.h	Wed Dec 20 03:31:39 2000
+++ wakeone/include/linux/sched.h	Wed Dec 20 03:35:34 2000
@@ -252,7 +252,6 @@
 	struct task_struct *next_task, *prev_task;
 	struct task_struct *next_run,  *prev_run;
 
-	unsigned int task_exclusive;	/* task wants wake-one semantics in __wake_up() */
 /* task state */
 	struct linux_binfmt *binfmt;
 	int exit_code, exit_signal;
@@ -375,7 +374,6 @@
 /* counter */	DEF_PRIORITY,DEF_PRIORITY,0, \
 /* SMP */	0,0,0,-1, \
 /* schedlink */	&init_task,&init_task, &init_task, &init_task, \
-/* task_exclusive */ 0, \
 /* binfmt */	NULL, \
 /* ec,brk... */	0,0,0,0,0,0, \
 /* pid etc.. */	0,0,0,0,0, \
@@ -502,8 +500,8 @@
 						    signed long timeout));
 extern void FASTCALL(wake_up_process(struct task_struct * tsk));
 
-#define wake_up(x)			__wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE | TASK_EXCLUSIVE)
-#define wake_up_interruptible(x)	__wake_up((x),TASK_INTERRUPTIBLE | TASK_EXCLUSIVE)
+#define wake_up(x)			__wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE)
+#define wake_up_interruptible(x)	__wake_up((x),TASK_INTERRUPTIBLE)
 
 #define __set_current_state(state_value)	do { current->state = state_value; } while (0)
 #ifdef __SMP__
diff -urN 2.2.19pre2/kernel/sched.c wakeone/kernel/sched.c
--- 2.2.19pre2/kernel/sched.c	Wed Dec 20 03:31:39 2000
+++ wakeone/kernel/sched.c	Wed Dec 20 03:35:34 2000
@@ -727,7 +727,7 @@
 		goto move_rr_last;
 move_rr_back:
 
-	switch (prev->state) {
+	switch (prev->state & ~TASK_EXCLUSIVE) {
 		case TASK_INTERRUPTIBLE:
 			if (signal_pending(prev)) {
 				prev->state = TASK_RUNNING;
@@ -890,9 +890,9 @@
  */
 void __wake_up(struct wait_queue **q, unsigned int mode)
 {
-	struct task_struct *p, *best_exclusive;
+	struct task_struct *p;
 	struct wait_queue *head, *next;
-	unsigned int do_exclusive;
+	int wake_one = 0;
 
         if (!q)
 		goto out;
@@ -907,23 +907,27 @@
 	if (!next)
 		goto out_unlock;
 
-	best_exclusive = 0;
-	do_exclusive = mode & TASK_EXCLUSIVE;
 	while (next != head) {
 		p = next->task;
 		next = next->next;
 		if (p->state & mode) {
-			if (do_exclusive && p->task_exclusive) {
-				if (best_exclusive == NULL)
-					best_exclusive = p;
+			if (p->state & TASK_EXCLUSIVE) {
+				if (wake_one)
+					continue;
+				wake_one = 1;
 			}
-			else {
+			/*
+			 * 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;
 			}
+			wake_up_process(p);
 		}
 	}
-	if (best_exclusive)
-		wake_up_process(best_exclusive);
 out_unlock:
 	read_unlock(&waitqueue_lock);
 out:
@@ -1221,7 +1225,7 @@
 	read_lock(&tasklist_lock);
 	for_each_task(p) {
 		if ((p->state == TASK_RUNNING ||
-		     p->state == TASK_UNINTERRUPTIBLE ||
+		     p->state & TASK_UNINTERRUPTIBLE ||
 		     p->state == TASK_SWAPPING))
 			nr += FIXED_1;
 	}
diff -urN 2.2.19pre2/kernel/signal.c wakeone/kernel/signal.c
--- 2.2.19pre2/kernel/signal.c	Thu May  4 13:00:40 2000
+++ wakeone/kernel/signal.c	Wed Dec 20 03:35:34 2000
@@ -394,7 +394,7 @@
 
 out:
 	spin_unlock_irqrestore(&t->sigmask_lock, flags);
-        if (t->state == TASK_INTERRUPTIBLE && signal_pending(t))
+        if (t->state & TASK_INTERRUPTIBLE && signal_pending(t))
                 wake_up_process(t);
 
 out_nolock:
diff -urN 2.2.19pre2/net/ipv4/tcp.c wakeone/net/ipv4/tcp.c
--- 2.2.19pre2/net/ipv4/tcp.c	Wed Dec 20 03:31:39 2000
+++ wakeone/net/ipv4/tcp.c	Wed Dec 20 03:35:34 2000
@@ -1619,10 +1619,9 @@
 	struct wait_queue wait = { current, NULL };
 	struct open_request *req;
 
-	current->task_exclusive = 1;
 	add_wait_queue(sk->sleep, &wait);
 	for (;;) {
-		current->state = TASK_INTERRUPTIBLE;
+		current->state = TASK_INTERRUPTIBLE | TASK_EXCLUSIVE;
 		release_sock(sk);
 		schedule();
 		lock_sock(sk);
@@ -1633,8 +1632,6 @@
 			break;
 	}
 	current->state = TASK_RUNNING;
-	wmb();
-	current->task_exclusive = 0;
 	remove_wait_queue(sk->sleep, &wait);
 	return req;
 }