patch-2.2.11 linux/net/ipv4/tcp.c
Next file: linux/net/ipv4/tcp_input.c
Previous file: linux/net/ipv4/sysctl_net_ipv4.c
Back to the patch index
Back to the overall index
- Lines: 91
- Date:
Mon Aug 9 12:05:45 1999
- Orig file:
v2.2.10/linux/net/ipv4/tcp.c
- Orig date:
Wed Jun 2 09:55:22 1999
diff -u --recursive --new-file v2.2.10/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
@@ -5,7 +5,7 @@
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp.c,v 1.140.2.1 1999/05/29 04:16:48 davem Exp $
+ * Version: $Id: tcp.c,v 1.140.2.4 1999/08/09 03:13:12 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -725,6 +725,23 @@
lock_sock(sk);
}
+/*
+ * Wait for a buffer.
+ */
+static int wait_for_buffer(struct sock *sk)
+{
+ struct wait_queue wait = { current, NULL };
+
+ release_sock(sk);
+ add_wait_queue(sk->sleep, &wait);
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ current->state = TASK_RUNNING;
+ remove_wait_queue(sk->sleep, &wait);
+ lock_sock(sk);
+ return 0;
+}
+
/* When all user supplied data has been queued set the PSH bit */
#define PSH_NEEDED (seglen == 0 && iovlen == 0)
@@ -802,11 +819,21 @@
tp->snd_nxt < TCP_SKB_CB(skb)->end_seq) {
int last_byte_was_odd = (copy % 4);
+ /*
+ * Check for parallel writers sleeping in user access.
+ */
+ if (tp->partial_writers++ > 0) {
+ wait_for_buffer(sk);
+ tp->partial_writers--;
+ continue;
+ }
+
copy = mss_now - copy;
if(copy > skb_tailroom(skb))
copy = skb_tailroom(skb);
if(copy > seglen)
copy = seglen;
+
if(last_byte_was_odd) {
if(copy_from_user(skb_put(skb, copy),
from, copy))
@@ -819,6 +846,7 @@
from, skb_put(skb, copy),
copy, skb->csum, &err);
}
+
/*
* FIXME: the *_user functions should
* return how much data was
@@ -838,6 +866,10 @@
seglen -= copy;
if (PSH_NEEDED)
TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH;
+
+ if (--tp->partial_writers > 0)
+ wake_up_interruptible(sk->sleep);
+
continue;
}
}
@@ -1332,12 +1364,12 @@
break;
}
- if(copied > 0 && msg->msg_name)
+ if(copied >= 0 && msg->msg_name) {
tp->af_specific->addr2sockaddr(sk, (struct sockaddr *)
msg->msg_name);
-
- if(addr_len)
- *addr_len = tp->af_specific->sockaddr_len;
+ if(addr_len)
+ *addr_len = tp->af_specific->sockaddr_len;
+ }
remove_wait_queue(sk->sleep, &wait);
current->state = TASK_RUNNING;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)