diff options
author | Vitaliy Makkoveev <mvs@cvs.openbsd.org> | 2022-07-01 09:56:18 +0000 |
---|---|---|
committer | Vitaliy Makkoveev <mvs@cvs.openbsd.org> | 2022-07-01 09:56:18 +0000 |
commit | 330cd6e874a18fa481c8b57a0e30f3850f24e39c (patch) | |
tree | 66960465c1d51317668f36763e40af70a3d95ff7 /sys/miscfs/fifofs | |
parent | 02a36ca46695152cacd5ccf441f740f65785e838 (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.c | 10 |
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); |