Make fine grained unix(4) domain sockets locking. Use the per-socket
authormvs <mvs@openbsd.org>
Fri, 1 Jul 2022 09:56:17 +0000 (09:56 +0000)
committermvs <mvs@openbsd.org>
Fri, 1 Jul 2022 09:56:17 +0000 (09:56 +0000)
commitcf85347fcaf1b04df91f85820772f5ae84768baf
tree3b478d9c7a1eb6a8719a1ca444e50d369d5dff07
parent74158beac1edd1d22821a1dab07ca6bf1ad63a76
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@
sys/kern/uipc_socket.c
sys/kern/uipc_socket2.c
sys/kern/uipc_syscalls.c
sys/kern/uipc_usrreq.c
sys/miscfs/fifofs/fifo_vnops.c
sys/sys/socketvar.h
sys/sys/unpcb.h