diff -ur --new-file linux-2.2.14/Makefile linux-2.2.14-taskex/Makefile
--- linux-2.2.14/Makefile	Wed Mar 22 23:08:43 2000
+++ linux-2.2.14-taskex/Makefile	Wed Mar 22 23:11:33 2000
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 2
 SUBLEVEL = 14
-EXTRAVERSION = 
+EXTRAVERSION = -taskex
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
diff -ur --new-file linux-2.2.14/include/linux/sched.h linux-2.2.14-taskex/include/linux/sched.h
--- linux-2.2.14/include/linux/sched.h	Wed Mar 22 23:13:54 2000
+++ linux-2.2.14-taskex/include/linux/sched.h	Wed Mar 22 23:53:21 2000
@@ -79,6 +79,7 @@
 #define TASK_ZOMBIE		4
 #define TASK_STOPPED		8
 #define TASK_SWAPPING		16
+#define TASK_EXCLUSIVE		32
 
 /*
  * Scheduling policies
@@ -686,17 +687,6 @@
 extern int do_execve(char *, char **, char **, struct pt_regs *);
 extern int do_fork(unsigned long, unsigned long, struct pt_regs *);
 
-/*
- * The wait-queues are circular lists, and you have to be *very* sure
- * to keep them correct. Use only these two functions to add/remove
- * entries in the queues.
- */
-extern inline void __add_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
-{
-	wait->next = *p ? : WAIT_QUEUE_HEAD(p);
-	*p = wait;
-}
-
 extern rwlock_t waitqueue_lock;
 
 extern inline void add_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
@@ -708,16 +698,13 @@
 	write_unlock_irqrestore(&waitqueue_lock, flags);
 }
 
-extern inline void __remove_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
+extern inline void add_wait_queue_exclusive(struct wait_queue ** p, struct wait_queue * wait)
 {
-	struct wait_queue * next = wait->next;
-	struct wait_queue * head = next;
-	struct wait_queue * tmp;
+	unsigned long flags;
 
-	while ((tmp = head->next) != wait) {
-		head = tmp;
-	}
-	head->next = next;
+        write_lock_irqsave(&waitqueue_lock, flags);
+        __add_wait_queue_tail(p, wait);
+        write_unlock_irqrestore(&waitqueue_lock, flags);
 }
 
 extern inline void remove_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
diff -ur --new-file linux-2.2.14/include/linux/wait.h linux-2.2.14-taskex/include/linux/wait.h
--- linux-2.2.14/include/linux/wait.h	Wed Mar 22 23:13:54 2000
+++ linux-2.2.14-taskex/include/linux/wait.h	Wed Mar 22 23:53:21 2000
@@ -17,6 +17,38 @@
 
 #define WAIT_QUEUE_HEAD(x) ((struct wait_queue *)((x)-1))
 
+extern inline void __add_wait_queue(struct wait_queue **p, struct wait_queue *wait)
+{
+       wait->next = *p ? : WAIT_QUEUE_HEAD(p);
+       *p = wait;
+       /* list_add(&new->task_list, &head->task_list); */
+}
+
+extern inline void __add_wait_queue_tail(struct wait_queue **p, struct wait_queue *wait)
+{
+       struct wait_queue * head = WAIT_QUEUE_HEAD(p);
+       struct wait_queue * tmp = *p;
+
+       while (tmp->next != head)
+               tmp = tmp->next;
+       wait->next = tmp->next;
+       tmp->next = wait;
+       /* list_add(&new->task_list, head->task_list.prev); */
+}
+
+extern inline void __remove_wait_queue(struct wait_queue **p, struct wait_queue *wait)
+{
+       struct wait_queue * next = wait->next;
+       struct wait_queue * head = next;
+       struct wait_queue * tmp;
+
+       while ((tmp = head->next) != wait) {
+               head = tmp;
+       }
+       head->next = next;
+       /* list_del(&old->task_list); */
+}
+
 static inline void init_waitqueue(struct wait_queue **q)
 {
 	*q = WAIT_QUEUE_HEAD(q);
diff -ur --new-file linux-2.2.14/kernel/sched.c linux-2.2.14-taskex/kernel/sched.c
--- linux-2.2.14/kernel/sched.c	Wed Mar 22 23:08:23 2000
+++ linux-2.2.14-taskex/kernel/sched.c	Wed Mar 22 23:47:30 2000
@@ -899,9 +899,12 @@
 		goto out_unlock;
 
 	while (next != head) {
+		unsigned int state;
+
 		p = next->task;
 		next = next->next;
-		if (p->state & mode) {
+		state = p->state;
+		if (state & mode) {
 			/*
 			 * We can drop the read-lock early if this
 			 * is the only/last process.
@@ -912,6 +915,8 @@
 				goto out;
 			}
 			wake_up_process(p);
+                        if (state & TASK_EXCLUSIVE)
+                                break;
 		}
 	}
 out_unlock:
@@ -1203,8 +1208,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);
diff -ur --new-file linux-2.2.14/kernel/signal.c linux-2.2.14-taskex/kernel/signal.c
--- linux-2.2.14/kernel/signal.c	Wed Mar 22 23:08:23 2000
+++ linux-2.2.14-taskex/kernel/signal.c	Wed Mar 22 23:48:33 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 -ur --new-file linux-2.2.14/net/core/sock.c linux-2.2.14-taskex/net/core/sock.c
--- linux-2.2.14/net/core/sock.c	Mon May 10 12:55:25 1999
+++ linux-2.2.14-taskex/net/core/sock.c	Wed Mar 22 23:49:48 2000
@@ -1036,7 +1036,8 @@
 		sk->type	=	sock->type;
 		sk->sleep	=	&sock->wait;
 		sock->sk	=	sk;
-	}
+	} else
+               sk->sleep       =       NULL;
 
 	sk->state_change	=	sock_def_wakeup;
 	sk->data_ready		=	sock_def_readable;
diff -ur --new-file linux-2.2.14/net/ipv4/tcp.c linux-2.2.14-taskex/net/ipv4/tcp.c
--- linux-2.2.14/net/ipv4/tcp.c	Wed Mar 22 23:08:24 2000
+++ linux-2.2.14-taskex/net/ipv4/tcp.c	Wed Mar 22 23:51:20 2000
@@ -1606,9 +1606,9 @@
 	struct wait_queue wait = { current, NULL };
 	struct open_request *req;
 
-	add_wait_queue(sk->sleep, &wait);
+	add_wait_queue_exclusive(sk->sleep, &wait);
 	for (;;) {
-		current->state = TASK_INTERRUPTIBLE;
+		current->state = TASK_EXCLUSIVE | TASK_INTERRUPTIBLE;
 		release_sock(sk);
 		schedule();
 		lock_sock(sk);
