Hi,
The next small step towards parallel network stack is to use shared
netlock in soreceive(). The UDP and IP divert layer provide locking
of the PCB. If that is possible, use shared instead of exclusive
netlock in soreceive(). The PCB mutex provides a per socket lock
against multiple soreceive() running in parallel.
The solock_shared() is a bit hacky. Especially where we have to
release and regrab both locks in sosleep_nsec(). But it does what
we need.
The udp_input() keeps exclusive lock for now. Socket splicing and
IP header chains are not completely MP safe yet. Also udp_input()
has some tentacles that need more testing.
Ok to procceed with soreceive() unlocking before release? I think
udp_input() has to wait post 7.2.
bluhm
Index: kern/uipc_socket.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/kern/uipc_socket.c,v
retrieving revision 1.287
diff -u -p -r1.287 uipc_socket.c
--- kern/uipc_socket.c 3 Sep 2022 13:29:33 -0000 1.287
+++ kern/uipc_socket.c 3 Sep 2022 19:23:43 -0000
@@ -822,10 +822,10 @@ bad:
if (mp)
*mp = NULL;
- solock(so);
+ solock_shared(so);
restart:
if ((error = sblock(so, &so->so_rcv, SBLOCKWAIT(flags))) != 0) {
- sounlock(so);
+ sounlock_shared(so);
return (error);
}
@@ -893,7 +893,7 @@ restart:
sbunlock(so, &so->so_rcv);
error = sbwait(so, &so->so_rcv);
if (error) {
- sounlock(so);
+ sounlock_shared(so);
return (error);
}
goto restart;
@@ -962,11 +962,11 @@ dontblock:
sbsync(&so->so_rcv, nextrecord);
if (controlp) {
if (pr->pr_domain->dom_externalize) {
- sounlock(so);
+ sounlock_shared(so);
error =
(*pr->pr_domain->dom_externalize)
(cm, controllen, flags);
- solock(so);
+ solock_shared(so);
}
*controlp = cm;
} else {
@@ -1040,9 +1040,9 @@ dontblock:
SBLASTRECORDCHK(&so->so_rcv, "soreceive uiomove");
SBLASTMBUFCHK(&so->so_rcv, "soreceive uiomove");
resid = uio->uio_resid;
- sounlock(so);
+ sounlock_shared(so);
uio_error = uiomove(mtod(m, caddr_t) + moff, len, uio);
- solock(so);
+ solock_shared(so);
if (uio_error)
uio->uio_resid = resid - len;
} else
@@ -1126,7 +1126,7 @@ dontblock:
error = sbwait(so, &so->so_rcv);
if (error) {
sbunlock(so, &so->so_rcv);
- sounlock(so);
+ sounlock_shared(so);
return (0);
}
if ((m = so->so_rcv.sb_mb) != NULL)
@@ -1171,7 +1171,7 @@ dontblock:
*flagsp |= flags;
release:
sbunlock(so, &so->so_rcv);
- sounlock(so);
+ sounlock_shared(so);
return (error);
}
Index: kern/uipc_socket2.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/kern/uipc_socket2.c,v
retrieving revision 1.127
diff -u -p -r1.127 uipc_socket2.c
--- kern/uipc_socket2.c 13 Aug 2022 21:01:46 -0000 1.127
+++ kern/uipc_socket2.c 3 Sep 2022 19:23:43 -0000
@@ -360,6 +360,24 @@ solock(struct socket *so)
}
}
+void
+solock_shared(struct socket *so)
+{
+ switch (so->so_proto->pr_domain->dom_family) {
+ case PF_INET:
+ case PF_INET6:
+ if (so->so_proto->pr_usrreqs->pru_lock != NULL) {
+ NET_LOCK_SHARED();
+ pru_lock(so);
+ } else
+ NET_LOCK();
+ break;
+ default:
+ rw_enter_write(&so->so_lock);
+ break;
+ }
+}
+
int
solock_persocket(struct socket *so)
{
@@ -403,6 +421,24 @@ sounlock(struct socket *so)
}
void
+sounlock_shared(struct socket *so)
+{
+ switch (so->so_proto->pr_domain->dom_family) {
+ case PF_INET:
+ case PF_INET6:
+ if (so->so_proto->pr_usrreqs->pru_unlock != NULL) {
+ pru_unlock(so);
+ NET_UNLOCK_SHARED();
+ } else
+ NET_UNLOCK();
+ break;
+ default:
+ rw_exit_write(&so->so_lock);
+ break;
+ }
+}
+
+void
soassertlocked(struct socket *so)
{
switch (so->so_proto->pr_domain->dom_family) {
@@ -425,7 +461,15 @@ sosleep_nsec(struct socket *so, void *id
switch (so->so_proto->pr_domain->dom_family) {
case PF_INET:
case PF_INET6:
+ if (so->so_proto->pr_usrreqs->pru_unlock != NULL &&
+ rw_status(&netlock) == RW_READ) {
+ pru_unlock(so);
+ }
ret = rwsleep_nsec(ident, &netlock, prio, wmesg, nsecs);
+ if (so->so_proto->pr_usrreqs->pru_lock != NULL &&
+ rw_status(&netlock) == RW_READ) {
+ pru_lock(so);
+ }
break;
default:
ret = rwsleep_nsec(ident, &so->so_lock, prio, wmesg, nsecs);
Index: netinet/ip_divert.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_divert.c,v
retrieving revision 1.85
diff -u -p -r1.85 ip_divert.c
--- netinet/ip_divert.c 3 Sep 2022 18:48:50 -0000 1.85
+++ netinet/ip_divert.c 3 Sep 2022 19:23:43 -0000
@@ -66,6 +66,8 @@ const struct pr_usrreqs divert_usrreqs =
.pru_usrreq = divert_usrreq,
.pru_attach = divert_attach,
.pru_detach = divert_detach,
+ .pru_lock = divert_lock,
+ .pru_unlock = divert_unlock,
.pru_bind = divert_bind,
.pru_shutdown = divert_shutdown,
.pru_send = divert_send,
@@ -325,6 +327,24 @@ divert_detach(struct socket *so)
in_pcbdetach(inp);
return (0);
+}
+
+void
+divert_lock(struct socket *so)
+{
+ struct inpcb *inp = sotoinpcb(so);
+
+ NET_ASSERT_LOCKED();
+ mtx_enter(&inp->inp_mtx);
+}
+
+void
+divert_unlock(struct socket *so)
+{
+ struct inpcb *inp = sotoinpcb(so);
+
+ NET_ASSERT_LOCKED();
+ mtx_leave(&inp->inp_mtx);
}
int
Index: netinet/ip_divert.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_divert.h,v
retrieving revision 1.20
diff -u -p -r1.20 ip_divert.h
--- netinet/ip_divert.h 28 Aug 2022 18:44:16 -0000 1.20
+++ netinet/ip_divert.h 3 Sep 2022 19:23:43 -0000
@@ -74,6 +74,8 @@ int divert_usrreq(struct socket *,
int, struct mbuf *, struct mbuf *, struct mbuf *, struct proc *);
int divert_attach(struct socket *, int);
int divert_detach(struct socket *);
+void divert_lock(struct socket *);
+void divert_unlock(struct socket *);
int divert_bind(struct socket *, struct mbuf *, struct proc *);
int divert_shutdown(struct socket *);
int divert_send(struct socket *, struct mbuf *, struct mbuf *,
Index: netinet/udp_usrreq.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/udp_usrreq.c,v
retrieving revision 1.300
diff -u -p -r1.300 udp_usrreq.c
--- netinet/udp_usrreq.c 3 Sep 2022 18:48:50 -0000 1.300
+++ netinet/udp_usrreq.c 3 Sep 2022 19:23:43 -0000
@@ -126,6 +126,8 @@ const struct pr_usrreqs udp_usrreqs = {
.pru_usrreq = udp_usrreq,
.pru_attach = udp_attach,
.pru_detach = udp_detach,
+ .pru_lock = udp_lock,
+ .pru_unlock = udp_unlock,
.pru_bind = udp_bind,
.pru_connect = udp_connect,
.pru_disconnect = udp_disconnect,
@@ -141,6 +143,8 @@ const struct pr_usrreqs udp6_usrreqs = {
.pru_usrreq = udp_usrreq,
.pru_attach = udp_attach,
.pru_detach = udp_detach,
+ .pru_lock = udp_lock,
+ .pru_unlock = udp_unlock,
.pru_bind = udp_bind,
.pru_connect = udp_connect,
.pru_disconnect = udp_disconnect,
@@ -1159,6 +1163,24 @@ udp_detach(struct socket *so)
in_pcbdetach(inp);
return (0);
+}
+
+void
+udp_lock(struct socket *so)
+{
+ struct inpcb *inp = sotoinpcb(so);
+
+ NET_ASSERT_LOCKED();
+ mtx_enter(&inp->inp_mtx);
+}
+
+void
+udp_unlock(struct socket *so)
+{
+ struct inpcb *inp = sotoinpcb(so);
+
+ NET_ASSERT_LOCKED();
+ mtx_leave(&inp->inp_mtx);
}
int
Index: netinet/udp_var.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/udp_var.h,v
retrieving revision 1.45
diff -u -p -r1.45 udp_var.h
--- netinet/udp_var.h 2 Sep 2022 13:12:32 -0000 1.45
+++ netinet/udp_var.h 3 Sep 2022 19:23:43 -0000
@@ -147,6 +147,8 @@ int udp_usrreq(struct socket *,
int, struct mbuf *, struct mbuf *, struct mbuf *, struct proc *);
int udp_attach(struct socket *, int);
int udp_detach(struct socket *);
+void udp_lock(struct socket *);
+void udp_unlock(struct socket *);
int udp_bind(struct socket *, struct mbuf *, struct proc *);
int udp_connect(struct socket *, struct mbuf *);
int udp_disconnect(struct socket *);
Index: netinet6/ip6_divert.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_divert.c,v
retrieving revision 1.84
diff -u -p -r1.84 ip6_divert.c
--- netinet6/ip6_divert.c 3 Sep 2022 18:48:50 -0000 1.84
+++ netinet6/ip6_divert.c 3 Sep 2022 19:23:43 -0000
@@ -67,6 +67,8 @@ const struct pr_usrreqs divert6_usrreqs
.pru_usrreq = divert6_usrreq,
.pru_attach = divert6_attach,
.pru_detach = divert6_detach,
+ .pru_lock = divert6_lock,
+ .pru_unlock = divert6_unlock,
.pru_bind = divert6_bind,
.pru_shutdown = divert6_shutdown,
.pru_send = divert6_send,
@@ -332,6 +334,24 @@ divert6_detach(struct socket *so)
in_pcbdetach(inp);
return (0);
+}
+
+void
+divert6_lock(struct socket *so)
+{
+ struct inpcb *inp = sotoinpcb(so);
+
+ NET_ASSERT_LOCKED();
+ mtx_enter(&inp->inp_mtx);
+}
+
+void
+divert6_unlock(struct socket *so)
+{
+ struct inpcb *inp = sotoinpcb(so);
+
+ NET_ASSERT_LOCKED();
+ mtx_leave(&inp->inp_mtx);
}
int
Index: netinet6/ip6_divert.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_divert.h,v
retrieving revision 1.18
diff -u -p -r1.18 ip6_divert.h
--- netinet6/ip6_divert.h 28 Aug 2022 18:44:17 -0000 1.18
+++ netinet6/ip6_divert.h 3 Sep 2022 19:23:43 -0000
@@ -74,6 +74,8 @@ int divert6_usrreq(struct socket *,
int, struct mbuf *, struct mbuf *, struct mbuf *, struct proc *);
int divert6_attach(struct socket *, int);
int divert6_detach(struct socket *);
+void divert6_lock(struct socket *);
+void divert6_unlock(struct socket *);
int divert6_bind(struct socket *, struct mbuf *, struct proc *);
int divert6_shutdown(struct socket *);
int divert6_send(struct socket *, struct mbuf *, struct mbuf *,
Index: sys/protosw.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/sys/protosw.h,v
retrieving revision 1.53
diff -u -p -r1.53 protosw.h
--- sys/protosw.h 3 Sep 2022 18:48:50 -0000 1.53
+++ sys/protosw.h 3 Sep 2022 19:23:43 -0000
@@ -68,6 +68,8 @@ struct pr_usrreqs {
int (*pru_attach)(struct socket *, int);
int (*pru_detach)(struct socket *);
+ void (*pru_lock)(struct socket *);
+ void (*pru_unlock)(struct socket *);
int (*pru_bind)(struct socket *, struct mbuf *, struct proc *);
int (*pru_listen)(struct socket *);
int (*pru_connect)(struct socket *, struct mbuf *);
@@ -277,6 +279,18 @@ static inline int
pru_detach(struct socket *so)
{
return (*so->so_proto->pr_usrreqs->pru_detach)(so);
+}
+
+static inline void
+pru_lock(struct socket *so)
+{
+ (*so->so_proto->pr_usrreqs->pru_lock)(so);
+}
+
+static inline void
+pru_unlock(struct socket *so)
+{
+ (*so->so_proto->pr_usrreqs->pru_unlock)(so);
}
static inline int
Index: sys/socketvar.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/sys/socketvar.h,v
retrieving revision 1.109
diff -u -p -r1.109 socketvar.h
--- sys/socketvar.h 1 Sep 2022 05:31:49 -0000 1.109
+++ sys/socketvar.h 3 Sep 2022 19:23:43 -0000
@@ -348,9 +348,11 @@ int sockargs(struct mbuf **, const void
int sosleep_nsec(struct socket *, void *, int, const char *, uint64_t);
void solock(struct socket *);
+void solock_shared(struct socket *);
int solock_persocket(struct socket *);
void solock_pair(struct socket *, struct socket *);
void sounlock(struct socket *);
+void sounlock_shared(struct socket *);
int sendit(struct proc *, int, struct msghdr *, int, register_t *);
int recvit(struct proc *, int, struct msghdr *, caddr_t, register_t *);