diff options
author | rwatson <rwatson@FreeBSD.org> | 2004-06-18 02:57:55 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2004-06-18 02:57:55 +0000 |
commit | d87fad9f086c5e1c8af4ba8e1373bcc73f21dce5 (patch) | |
tree | f8e2158ca72e6e07a6df949c4ae028022ce2f5d0 /sys/fs | |
parent | 48317d5cbf6fc60d08d669d945662e451113a578 (diff) | |
download | FreeBSD-src-d87fad9f086c5e1c8af4ba8e1373bcc73f21dce5.zip FreeBSD-src-d87fad9f086c5e1c8af4ba8e1373bcc73f21dce5.tar.gz |
Merge some additional leaf node socket buffer locking from
rwatson_netperf:
Introduce conditional locking of the socket buffer in fifofs kqueue
filters; KNOTE() will be called holding the socket buffer locks in
fifofs, but sometimes the kqueue() system call will poll using the
same entry point without holding the socket buffer lock.
Introduce conditional locking of the socket buffer in the socket
kqueue filters; KNOTE() will be called holding the socket buffer
locks in the socket code, but sometimes the kqueue() system call
will poll using the same entry points without holding the socket
buffer lock.
Simplify the logic in sodisconnect() since we no longer need spls.
NOTE: To remove conditional locking in the kqueue filters, it would
make sense to use a separate kqueue API entry into the socket/fifo
code when calling from the kqueue() system call.
Diffstat (limited to 'sys/fs')
-rw-r--r-- | sys/fs/fifofs/fifo_vnops.c | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/sys/fs/fifofs/fifo_vnops.c b/sys/fs/fifofs/fifo_vnops.c index da9716b..373b582 100644 --- a/sys/fs/fifofs/fifo_vnops.c +++ b/sys/fs/fifofs/fifo_vnops.c @@ -444,23 +444,33 @@ filt_fifordetach(struct knote *kn) { struct socket *so = (struct socket *)kn->kn_hook; + SOCKBUF_LOCK(&so->so_rcv); SLIST_REMOVE(&so->so_rcv.sb_sel.si_note, kn, knote, kn_selnext); if (SLIST_EMPTY(&so->so_rcv.sb_sel.si_note)) so->so_rcv.sb_flags &= ~SB_KNOTE; + SOCKBUF_UNLOCK(&so->so_rcv); } static int filt_fiforead(struct knote *kn, long hint) { struct socket *so = (struct socket *)kn->kn_hook; + int need_lock, result; + need_lock = !SOCKBUF_OWNED(&so->so_rcv); + if (need_lock) + SOCKBUF_LOCK(&so->so_rcv); kn->kn_data = so->so_rcv.sb_cc; if (so->so_rcv.sb_state & SBS_CANTRCVMORE) { kn->kn_flags |= EV_EOF; - return (1); + result = 1; + } else { + kn->kn_flags &= ~EV_EOF; + result = (kn->kn_data > 0); } - kn->kn_flags &= ~EV_EOF; - return (kn->kn_data > 0); + if (need_lock) + SOCKBUF_UNLOCK(&so->so_rcv); + return (result); } static void @@ -468,23 +478,34 @@ filt_fifowdetach(struct knote *kn) { struct socket *so = (struct socket *)kn->kn_hook; + SOCKBUF_LOCK(&so->so_snd); SLIST_REMOVE(&so->so_snd.sb_sel.si_note, kn, knote, kn_selnext); if (SLIST_EMPTY(&so->so_snd.sb_sel.si_note)) so->so_snd.sb_flags &= ~SB_KNOTE; + SOCKBUF_UNLOCK(&so->so_snd); } static int filt_fifowrite(struct knote *kn, long hint) { struct socket *so = (struct socket *)kn->kn_hook; + int need_lock, result; + need_lock = !SOCKBUF_OWNED(&so->so_snd); + if (need_lock) + SOCKBUF_LOCK(&so->so_snd); kn->kn_data = sbspace(&so->so_snd); + /* Unlocked read. */ if (so->so_snd.sb_state & SBS_CANTSENDMORE) { kn->kn_flags |= EV_EOF; - return (1); + result = 1; + } else { + kn->kn_flags &= ~EV_EOF; + result = (kn->kn_data >= so->so_snd.sb_lowat); } - kn->kn_flags &= ~EV_EOF; - return (kn->kn_data >= so->so_snd.sb_lowat); + if (need_lock) + SOCKBUF_UNLOCK(&so->so_snd); + return (result); } /* ARGSUSED */ |