Index | Thread | Search

From:
Vitaliy Makkoveev <mvs@openbsd.org>
Subject:
Please test: shared solock for all intet sockets within knote(9) routines
To:
tech@openbsd.org
Date:
Fri, 26 Jan 2024 19:59:02 +0300

Download raw body.

Thread
Not for commit yet, but could be interesting. The idea is the same as
for PCB layer: take shared netlock and exclusive `so_lock' to serialize
access to the socket. The tcp(4) sockets permit this because knote(9)
routines do read-only access to sockets.

Should provide some additional performance.

Index: sys/kern/uipc_socket.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_socket.c,v
retrieving revision 1.314
diff -u -p -r1.314 uipc_socket.c
--- sys/kern/uipc_socket.c	12 Jan 2024 10:48:03 -0000	1.314
+++ sys/kern/uipc_socket.c	26 Jan 2024 16:50:58 -0000
@@ -2135,13 +2135,43 @@ sohasoutofband(struct socket *so)
 	knote_locked(&so->so_rcv.sb_klist, 0);
 }
 
+void
+sofilt_lock(struct socket *so)
+{
+	switch (so->so_proto->pr_domain->dom_family) {
+	case PF_INET:
+	case PF_INET6:
+		NET_LOCK_SHARED();
+		rw_enter_write(&so->so_lock);
+		break;
+	default:
+		rw_enter_write(&so->so_lock);
+		break;
+	}
+}
+
+void
+sofilt_unlock(struct socket *so)
+{
+	switch (so->so_proto->pr_domain->dom_family) {
+	case PF_INET:
+	case PF_INET6:
+		rw_exit_write(&so->so_lock);
+		NET_UNLOCK_SHARED();
+		break;
+	default:
+		rw_exit_write(&so->so_lock);
+		break;
+	}
+}
+
 int
 soo_kqfilter(struct file *fp, struct knote *kn)
 {
 	struct socket *so = kn->kn_fp->f_data;
 	struct sockbuf *sb;
 
-	solock(so);
+	sofilt_lock(so);
 	switch (kn->kn_filter) {
 	case EVFILT_READ:
 		if (so->so_options & SO_ACCEPTCONN)
@@ -2159,12 +2189,12 @@ soo_kqfilter(struct file *fp, struct kno
 		sb = &so->so_rcv;
 		break;
 	default:
-		sounlock(so);
+		sofilt_unlock(so);
 		return (EINVAL);
 	}
 
 	klist_insert_locked(&sb->sb_klist, kn);
-	sounlock(so);
+	sofilt_unlock(so);
 
 	return (0);
 }
@@ -2185,6 +2215,8 @@ filt_soread(struct knote *kn, long hint)
 
 	soassertlocked(so);
 
+	pru_lock(so);
+
 	kn->kn_data = so->so_rcv.sb_cc;
 #ifdef SOCKET_SPLICE
 	if (isspliced(so)) {
@@ -2207,6 +2239,8 @@ filt_soread(struct knote *kn, long hint)
 		rv = (kn->kn_data >= so->so_rcv.sb_lowat);
 	}
 
+	pru_unlock(so);
+
 	return rv;
 }
 
@@ -2226,6 +2260,8 @@ filt_sowrite(struct knote *kn, long hint
 
 	soassertlocked(so);
 
+	pru_lock(so);
+
 	kn->kn_data = sbspace(so, &so->so_snd);
 	if (so->so_snd.sb_state & SS_CANTSENDMORE) {
 		kn->kn_flags |= EV_EOF;
@@ -2246,6 +2282,8 @@ filt_sowrite(struct knote *kn, long hint
 		rv = (kn->kn_data >= so->so_snd.sb_lowat);
 	}
 
+	pru_unlock(so);
+
 	return (rv);
 }
 
@@ -2309,9 +2347,9 @@ filt_somodify(struct kevent *kev, struct
 	struct socket *so = kn->kn_fp->f_data;
 	int rv;
 
-	solock(so);
+	sofilt_lock(so);
 	rv = knote_modify(kev, kn);
-	sounlock(so);
+	sofilt_unlock(so);
 
 	return (rv);
 }
@@ -2322,9 +2360,9 @@ filt_soprocess(struct knote *kn, struct 
 	struct socket *so = kn->kn_fp->f_data;
 	int rv;
 
-	solock(so);
+	sofilt_lock(so);
 	rv = knote_process(kn, kev);
-	sounlock(so);
+	sofilt_unlock(so);
 
 	return (rv);
 }
@@ -2342,7 +2380,7 @@ klist_solock(void *arg)
 {
 	struct socket *so = arg;
 
-	solock(so);
+	sofilt_lock(so);
 	return (1);
 }
 
@@ -2351,7 +2389,7 @@ klist_sounlock(void *arg, int ls)
 {
 	struct socket *so = arg;
 
-	sounlock(so);
+	sofilt_unlock(so);
 }
 
 #ifdef DDB