summaryrefslogtreecommitdiff
path: root/sys/miscfs/fifofs
diff options
context:
space:
mode:
authorVitaliy Makkoveev <mvs@cvs.openbsd.org>2022-07-01 09:56:18 +0000
committerVitaliy Makkoveev <mvs@cvs.openbsd.org>2022-07-01 09:56:18 +0000
commit330cd6e874a18fa481c8b57a0e30f3850f24e39c (patch)
tree66960465c1d51317668f36763e40af70a3d95ff7 /sys/miscfs/fifofs
parent02a36ca46695152cacd5ccf441f740f65785e838 (diff)
Make fine grained unix(4) domain sockets locking. Use the per-socket
`so_lock' rwlock(9) instead of global `unp_lock' which locks the whole layer. The PCB of unix(4) sockets are linked to each other and we need to lock them both. This introduces the lock ordering problem, because when the thread (1) keeps lock on `so1' and trying to lock `so2', the thread (2) could hold lock on `so2' and trying to lock `so1'. To solve this we always lock sockets in the strict order. For the sockets which are already accessible from userland, we always lock socket with the smallest memory address first. Sometimes we need to unlock socket before lock it's peer and lock it again. We use reference counters for prevent the connected peer destruction during to relock. We also handle the case where the peer socket was replaced by another socket. For the newly connected sockets, which are not yet exported to the userland by accept(2), we always lock the listening socket `head' first. This allows us to avoid unwanted relock within accept(2) syscall. ok claudio@
Diffstat (limited to 'sys/miscfs/fifofs')
-rw-r--r--sys/miscfs/fifofs/fifo_vnops.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/sys/miscfs/fifofs/fifo_vnops.c b/sys/miscfs/fifofs/fifo_vnops.c
index ff62072ccdb..d4f5df4d2c7 100644
--- a/sys/miscfs/fifofs/fifo_vnops.c
+++ b/sys/miscfs/fifofs/fifo_vnops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fifo_vnops.c,v 1.95 2022/06/26 05:20:42 visa Exp $ */
+/* $OpenBSD: fifo_vnops.c,v 1.96 2022/07/01 09:56:17 mvs Exp $ */
/* $NetBSD: fifo_vnops.c,v 1.18 1996/03/16 23:52:42 christos Exp $ */
/*
@@ -176,15 +176,17 @@ fifo_open(void *v)
solock(wso);
wso->so_state |= SS_CANTSENDMORE;
wso->so_snd.sb_lowat = PIPE_BUF;
+ sounlock(wso);
} else {
rso = fip->fi_readsock;
wso = fip->fi_writesock;
- solock(wso);
}
if (ap->a_mode & FREAD) {
fip->fi_readers++;
if (fip->fi_readers == 1) {
+ solock(wso);
wso->so_state &= ~SS_CANTSENDMORE;
+ sounlock(wso);
if (fip->fi_writers > 0)
wakeup(&fip->fi_writers);
}
@@ -193,16 +195,16 @@ fifo_open(void *v)
fip->fi_writers++;
if ((ap->a_mode & O_NONBLOCK) && fip->fi_readers == 0) {
error = ENXIO;
- sounlock(wso);
goto bad;
}
if (fip->fi_writers == 1) {
+ solock(rso);
rso->so_state &= ~(SS_CANTRCVMORE|SS_ISDISCONNECTED);
+ sounlock(rso);
if (fip->fi_readers > 0)
wakeup(&fip->fi_readers);
}
}
- sounlock(wso);
if ((ap->a_mode & O_NONBLOCK) == 0) {
if ((ap->a_mode & FREAD) && fip->fi_writers == 0) {
VOP_UNLOCK(vp);