diff -ur linux-2.3.12-ref/include/linux/sched.h linux-2.3.12-accept/include/linux/sched.h
--- linux-2.3.12-ref/include/linux/sched.h	Wed Aug  4 15:40:54 1999
+++ linux-2.3.12-accept/include/linux/sched.h	Fri Aug  6 11:14:28 1999
@@ -478,6 +478,8 @@
 
 #define wake_up(x)			__wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE)
 #define wake_up_interruptible(x)	__wake_up((x),TASK_INTERRUPTIBLE)
+#define wake_one(x)			__wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE | TASK_EXCLUSIVE)
+#define wake_one_interruptible(x)	__wake_up((x),TASK_INTERRUPTIBLE | TASK_EXCLUSIVE)
 
 extern int in_group_p(gid_t);
 
@@ -686,16 +688,6 @@
 
 	wq_write_lock_irqsave(&q->lock, flags);
 	__add_wait_queue(q, wait);
-	wq_write_unlock_irqrestore(&q->lock, flags);
-}
-
-extern inline void add_wait_queue_exclusive(wait_queue_head_t *q,
-							wait_queue_t * wait)
-{
-	unsigned long flags;
-
-	wq_write_lock_irqsave(&q->lock, flags);
-	__add_wait_queue_tail(q, wait);
 	wq_write_unlock_irqrestore(&q->lock, flags);
 }
 
diff -ur linux-2.3.12-ref/include/linux/wait.h linux-2.3.12-accept/include/linux/wait.h
--- linux-2.3.12-ref/include/linux/wait.h	Wed Aug  4 15:38:39 1999
+++ linux-2.3.12-accept/include/linux/wait.h	Fri Aug  6 11:15:28 1999
@@ -169,23 +169,6 @@
 	list_add(&new->task_list, &head->task_list);
 }
 
-/*
- * Used for wake-one threads:
- */
-extern inline void __add_wait_queue_tail(wait_queue_head_t *head,
-						wait_queue_t *new)
-{
-#if WAITQUEUE_DEBUG
-	if (!head || !new)
-		WQ_BUG();
-	CHECK_MAGIC_WQHEAD(head);
-	CHECK_MAGIC(new->__magic);
-	if (!head->task_list.next || !head->task_list.prev)
-		WQ_BUG();
-#endif
-	list_add(&new->task_list, head->task_list.prev);
-}
-
 extern inline void __remove_wait_queue(wait_queue_head_t *head,
 							wait_queue_t *old)
 {
diff -ur linux-2.3.12-ref/include/net/tcp.h linux-2.3.12-accept/include/net/tcp.h
--- linux-2.3.12-ref/include/net/tcp.h	Wed Aug  4 15:40:27 1999
+++ linux-2.3.12-accept/include/net/tcp.h	Fri Aug  6 13:45:12 1999
@@ -483,6 +483,8 @@
 extern struct sock *		tcp_accept(struct sock *sk, int flags);
 extern unsigned int		tcp_poll(struct file * file, struct socket *sock, struct poll_table_struct *wait);
 extern void			tcp_write_space(struct sock *sk); 
+extern void			tcp_wakeup(struct sock *sk); 
+extern void			tcp_data_ready(struct sock *sk, int len); 
 
 extern int			tcp_getsockopt(struct sock *sk, int level, 
 					       int optname, char *optval, 
diff -ur linux-2.3.12-ref/kernel/sched.c linux-2.3.12-accept/kernel/sched.c
--- linux-2.3.12-ref/kernel/sched.c	Wed Aug  4 15:40:54 1999
+++ linux-2.3.12-accept/kernel/sched.c	Fri Aug  6 11:16:50 1999
@@ -857,15 +857,7 @@
 
 	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;
@@ -873,17 +865,11 @@
 
 		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)
+			if (TASK_EXCLUSIVE & mode)
 				break;
 		}
 	}
diff -ur linux-2.3.12-ref/net/core/sock.c linux-2.3.12-accept/net/core/sock.c
--- linux-2.3.12-ref/net/core/sock.c	Wed Aug  4 15:38:39 1999
+++ linux-2.3.12-accept/net/core/sock.c	Fri Aug  6 13:06:29 1999
@@ -742,9 +742,9 @@
 	if(sk->lock.users != 0) {
 		DECLARE_WAITQUEUE(wait, current);
 
-		add_wait_queue_exclusive(&sk->lock.wq, &wait);
+		add_wait_queue(&sk->lock.wq, &wait);
 		for(;;) {
-			current->state = TASK_EXCLUSIVE | TASK_UNINTERRUPTIBLE;
+			current->state = TASK_UNINTERRUPTIBLE;
 			spin_unlock_bh(&sk->lock.slock);
 			schedule();
 			spin_lock_bh(&sk->lock.slock);
diff -ur linux-2.3.12-ref/net/ipv4/tcp.c linux-2.3.12-accept/net/ipv4/tcp.c
--- linux-2.3.12-ref/net/ipv4/tcp.c	Wed Aug  4 15:40:33 1999
+++ linux-2.3.12-accept/net/ipv4/tcp.c	Fri Aug  6 13:48:43 1999
@@ -614,12 +614,31 @@
 	if (sk->dead)
 		return; 
 
-	wake_up_interruptible(sk->sleep);
+	wake_one_interruptible(sk->sleep);
 	if (sock_wspace(sk) >=
 	    tcp_min_write_space(sk))
 		sock_wake_async(sk->socket, 2);
 }
 
+/*
+ *     Socket state_change callback.
+ */
+void tcp_wakeup(struct sock *sk)
+{
+	if(!sk->dead)
+		wake_one_interruptible(sk->sleep);
+}
+
+/*
+ *     Socket data_ready callback.
+ */
+void tcp_data_ready(struct sock *sk, int len)
+{
+	if(!sk->dead) {
+		wake_one_interruptible(sk->sleep);
+		sock_wake_async(sk->socket,1);
+	}
+}
 
 int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
 {
@@ -1582,18 +1601,10 @@
 	 * one process gets woken up, not the 'whole herd'.
 	 * Since we do not 'race & poll' for established sockets
 	 * anymore, the common case will execute the loop only once.
-	 *
-	 * Subtle issue: "add_wait_queue_exclusive()" will be added
-	 * after any current non-exclusive waiters, and we know that
-	 * it will always _stay_ after any new non-exclusive waiters
-	 * because all non-exclusive waiters are added at the
-	 * beginning of the wait-queue. As such, it's ok to "drop"
-	 * our exclusiveness temporarily when we get woken up without
-	 * having to remove and re-insert us on the wait queue.
 	 */
-	add_wait_queue_exclusive(sk->sleep, &wait);
+	add_wait_queue(sk->sleep, &wait);
 	for (;;) {
-		current->state = TASK_EXCLUSIVE | TASK_INTERRUPTIBLE;
+		current->state = TASK_INTERRUPTIBLE;
 		release_sock(sk);
 		schedule();
 		lock_sock(sk);
diff -ur linux-2.3.12-ref/net/ipv4/tcp_ipv4.c linux-2.3.12-accept/net/ipv4/tcp_ipv4.c
--- linux-2.3.12-ref/net/ipv4/tcp_ipv4.c	Wed Aug  4 15:40:55 1999
+++ linux-2.3.12-accept/net/ipv4/tcp_ipv4.c	Fri Aug  6 13:49:09 1999
@@ -1355,6 +1355,8 @@
 		newsk->backlog.head = newsk->backlog.tail = NULL;
 		skb_queue_head_init(&newsk->error_queue);
 		newsk->write_space = tcp_write_space;
+		newsk->state_change = tcp_wakeup;
+		newsk->data_ready = tcp_data_ready;
 #ifdef CONFIG_FILTER
 		if ((filter = newsk->filter) != NULL)
 			sk_filter_charge(newsk, filter);
@@ -1940,6 +1942,8 @@
 	tp->rcv_mss = 536; 
 
 	sk->write_space = tcp_write_space; 
+	sk->state_change = tcp_wakeup;
+	sk->data_ready = tcp_data_ready;
 
 	/* Init SYN queue. */
 	tcp_synq_init(tp);
diff -ur linux-2.3.12-ref/net/netsyms.c linux-2.3.12-accept/net/netsyms.c
--- linux-2.3.12-ref/net/netsyms.c	Wed Aug  4 15:40:35 1999
+++ linux-2.3.12-accept/net/netsyms.c	Fri Aug  6 13:48:16 1999
@@ -296,6 +296,8 @@
 EXPORT_SYMBOL(tcp_write_wakeup);
 EXPORT_SYMBOL(tcp_read_wakeup);
 EXPORT_SYMBOL(tcp_write_space);
+EXPORT_SYMBOL(tcp_wakeup);
+EXPORT_SYMBOL(tcp_data_ready);
 EXPORT_SYMBOL(tcp_poll);
 EXPORT_SYMBOL(tcp_ioctl);
 EXPORT_SYMBOL(tcp_shutdown);
