summaryrefslogtreecommitdiffstats
path: root/sys/netinet/sctputil.c
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2007-05-03 14:42:42 +0000
committerrwatson <rwatson@FreeBSD.org>2007-05-03 14:42:42 +0000
commit20848234d96d64f1050c92166ebffc88afcc2fae (patch)
tree1bcae9ed15171271aa6fc97f1e539335630da9e9 /sys/netinet/sctputil.c
parent9bb125a79a492945d63a1509b80173d7740b1411 (diff)
downloadFreeBSD-src-20848234d96d64f1050c92166ebffc88afcc2fae.zip
FreeBSD-src-20848234d96d64f1050c92166ebffc88afcc2fae.tar.gz
sblock() implements a sleep lock by interlocking SB_WANT and SB_LOCK flags
on each socket buffer with the socket buffer's mutex. This sleep lock is used to serialize I/O on sockets in order to prevent I/O interlacing. This change replaces the custom sleep lock with an sx(9) lock, which results in marginally better performance, better handling of contention during simultaneous socket I/O across multiple threads, and a cleaner separation between the different layers of locking in socket buffers. Specifically, the socket buffer mutex is now solely responsible for serializing simultaneous operation on the socket buffer data structure, and not for I/O serialization. While here, fix two historic bugs: (1) a bug allowing I/O to be occasionally interlaced during long I/O operations (discovere by Isilon). (2) a bug in which failed non-blocking acquisition of the socket buffer I/O serialization lock might be ignored (discovered by sam). SCTP portion of this patch submitted by rrs.
Diffstat (limited to 'sys/netinet/sctputil.c')
-rw-r--r--sys/netinet/sctputil.c25
1 files changed, 10 insertions, 15 deletions
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index 0d0c270..bb1911d 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -3862,9 +3862,7 @@ sctp_pull_off_control_to_new_inp(struct sctp_inpcb *old_inp,
old_so = old_inp->sctp_socket;
new_so = new_inp->sctp_socket;
TAILQ_INIT(&tmp_queue);
- SOCKBUF_LOCK(&(old_so->so_rcv));
error = sblock(&old_so->so_rcv, waitflags);
- SOCKBUF_UNLOCK(&(old_so->so_rcv));
if (error) {
/*
* Gak, can't get sblock, we have a problem. data will be
@@ -3903,10 +3901,8 @@ sctp_pull_off_control_to_new_inp(struct sctp_inpcb *old_inp,
}
SCTP_INP_READ_UNLOCK(old_inp);
/* Remove the sb-lock on the old socket */
- SOCKBUF_LOCK(&(old_so->so_rcv));
sbunlock(&old_so->so_rcv);
- SOCKBUF_UNLOCK(&(old_so->so_rcv));
/* Now we move them over to the new socket buffer */
control = TAILQ_FIRST(&tmp_queue);
SCTP_INP_READ_LOCK(new_inp);
@@ -4521,6 +4517,7 @@ sctp_sorecvmsg(struct socket *so,
int alen = 0;
int slen = 0;
int held_length = 0;
+ int sockbuf_lock = 0;
if (msg_flags) {
in_flags = *msg_flags;
@@ -4558,8 +4555,6 @@ sctp_sorecvmsg(struct socket *so,
sctp_misc_ints(SCTP_SORECV_ENTER,
rwnd_req, in_eeor_mode, so->so_rcv.sb_cc, uio->uio_resid);
#endif
- SOCKBUF_LOCK(&so->so_rcv);
- hold_sblock = 1;
#ifdef SCTP_RECV_RWND_LOGGING
sctp_misc_ints(SCTP_SORECV_ENTERPL,
rwnd_req, block_allowed, so->so_rcv.sb_cc, uio->uio_resid);
@@ -4567,15 +4562,12 @@ sctp_sorecvmsg(struct socket *so,
error = sblock(&so->so_rcv, (block_allowed ? M_WAITOK : 0));
+ sockbuf_lock = 1;
if (error) {
goto release_unlocked;
}
restart:
- if (hold_sblock == 0) {
- SOCKBUF_LOCK(&so->so_rcv);
- hold_sblock = 1;
- }
- sbunlock(&so->so_rcv);
+
restart_nosblocks:
if (hold_sblock == 0) {
@@ -4704,7 +4696,6 @@ restart_nosblocks:
SOCKBUF_UNLOCK(&so->so_rcv);
hold_sblock = 0;
}
- error = sblock(&so->so_rcv, (block_allowed ? M_WAITOK : 0));
/* we possibly have data we can read */
control = TAILQ_FIRST(&inp->read_queue);
if (control == NULL) {
@@ -5529,11 +5520,12 @@ release:
SCTP_INP_READ_UNLOCK(inp);
hold_rlock = 0;
}
- if (hold_sblock == 0) {
- SOCKBUF_LOCK(&so->so_rcv);
- hold_sblock = 1;
+ if (hold_sblock == 1) {
+ SOCKBUF_UNLOCK(&so->so_rcv);
+ hold_sblock = 0;
}
sbunlock(&so->so_rcv);
+ sockbuf_lock = 0;
release_unlocked:
if (hold_sblock) {
@@ -5566,6 +5558,9 @@ out:
SOCKBUF_UNLOCK(&so->so_rcv);
hold_sblock = 0;
}
+ if (sockbuf_lock) {
+ sbunlock(&so->so_rcv);
+ }
if (freecnt_applied) {
/*
* The lock on the socket buffer protects us so the free
OpenPOWER on IntegriCloud