bhyve: vtnet: simplify thread synchronization
On vtnet device reset it is necessary to wait for threads to stop TX and RX processing. However, the rx_in_progress variable (used for to wait for RX processing to stop) is actually useless, and can be removed. Acquiring and releasing the RX lock is enough to synchronize correctly. Moreover, it is possible to reset the device while holding both TX and RX locks, so that the "resetting" variable becomes unnecessary for the RX thread, and can be protected by the TX lock (instead of being volatile). Reviewed by: jhb, markj MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D20543
This commit is contained in:
parent
af823c2295
commit
e5906c2293
@ -150,14 +150,13 @@ struct pci_vtnet_softc {
|
||||
struct nm_desc *vsc_nmd;
|
||||
|
||||
int vsc_rx_ready;
|
||||
volatile int resetting; /* set and checked outside lock */
|
||||
int resetting; /* protected by tx_mtx */
|
||||
|
||||
uint64_t vsc_features; /* negotiated features */
|
||||
|
||||
struct virtio_net_config vsc_config;
|
||||
|
||||
pthread_mutex_t rx_mtx;
|
||||
int rx_in_progress;
|
||||
int rx_vhdrlen;
|
||||
int rx_merge; /* merged rx bufs in use */
|
||||
|
||||
@ -189,38 +188,6 @@ static struct virtio_consts vtnet_vi_consts = {
|
||||
VTNET_S_HOSTCAPS, /* our capabilities */
|
||||
};
|
||||
|
||||
/*
|
||||
* If the transmit thread is active then stall until it is done.
|
||||
*/
|
||||
static void
|
||||
pci_vtnet_txwait(struct pci_vtnet_softc *sc)
|
||||
{
|
||||
|
||||
pthread_mutex_lock(&sc->tx_mtx);
|
||||
while (sc->tx_in_progress) {
|
||||
pthread_mutex_unlock(&sc->tx_mtx);
|
||||
usleep(10000);
|
||||
pthread_mutex_lock(&sc->tx_mtx);
|
||||
}
|
||||
pthread_mutex_unlock(&sc->tx_mtx);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the receive thread is active then stall until it is done.
|
||||
*/
|
||||
static void
|
||||
pci_vtnet_rxwait(struct pci_vtnet_softc *sc)
|
||||
{
|
||||
|
||||
pthread_mutex_lock(&sc->rx_mtx);
|
||||
while (sc->rx_in_progress) {
|
||||
pthread_mutex_unlock(&sc->rx_mtx);
|
||||
usleep(10000);
|
||||
pthread_mutex_lock(&sc->rx_mtx);
|
||||
}
|
||||
pthread_mutex_unlock(&sc->rx_mtx);
|
||||
}
|
||||
|
||||
static void
|
||||
pci_vtnet_reset(void *vsc)
|
||||
{
|
||||
@ -228,23 +195,32 @@ pci_vtnet_reset(void *vsc)
|
||||
|
||||
DPRINTF(("vtnet: device reset requested !\n"));
|
||||
|
||||
sc->resetting = 1;
|
||||
/* Acquire the RX lock to block RX processing. */
|
||||
pthread_mutex_lock(&sc->rx_mtx);
|
||||
|
||||
/*
|
||||
* Wait for the transmit and receive threads to finish their
|
||||
* processing.
|
||||
*/
|
||||
pci_vtnet_txwait(sc);
|
||||
pci_vtnet_rxwait(sc);
|
||||
/* Set sc->resetting and give a chance to the TX thread to stop. */
|
||||
pthread_mutex_lock(&sc->tx_mtx);
|
||||
sc->resetting = 1;
|
||||
while (sc->tx_in_progress) {
|
||||
pthread_mutex_unlock(&sc->tx_mtx);
|
||||
usleep(10000);
|
||||
pthread_mutex_lock(&sc->tx_mtx);
|
||||
}
|
||||
|
||||
sc->vsc_rx_ready = 0;
|
||||
sc->rx_merge = 1;
|
||||
sc->rx_vhdrlen = sizeof(struct virtio_net_rxhdr);
|
||||
|
||||
/* now reset rings, MSI-X vectors, and negotiated capabilities */
|
||||
/*
|
||||
* Now reset rings, MSI-X vectors, and negotiated capabilities.
|
||||
* Do that with the TX lock held, since we need to reset
|
||||
* sc->resetting.
|
||||
*/
|
||||
vi_reset_dev(&sc->vsc_vs);
|
||||
|
||||
sc->resetting = 0;
|
||||
pthread_mutex_unlock(&sc->tx_mtx);
|
||||
pthread_mutex_unlock(&sc->rx_mtx);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -318,9 +294,9 @@ pci_vtnet_tap_rx(struct pci_vtnet_softc *sc)
|
||||
|
||||
/*
|
||||
* But, will be called when the rx ring hasn't yet
|
||||
* been set up or the guest is resetting the device.
|
||||
* been set up.
|
||||
*/
|
||||
if (!sc->vsc_rx_ready || sc->resetting) {
|
||||
if (!sc->vsc_rx_ready) {
|
||||
/*
|
||||
* Drop the packet and try later.
|
||||
*/
|
||||
@ -515,9 +491,9 @@ pci_vtnet_netmap_rx(struct pci_vtnet_softc *sc)
|
||||
|
||||
/*
|
||||
* But, will be called when the rx ring hasn't yet
|
||||
* been set up or the guest is resetting the device.
|
||||
* been set up.
|
||||
*/
|
||||
if (!sc->vsc_rx_ready || sc->resetting) {
|
||||
if (!sc->vsc_rx_ready) {
|
||||
/*
|
||||
* Drop the packet and try later.
|
||||
*/
|
||||
@ -594,9 +570,7 @@ pci_vtnet_rx_callback(int fd, enum ev_type type, void *param)
|
||||
struct pci_vtnet_softc *sc = param;
|
||||
|
||||
pthread_mutex_lock(&sc->rx_mtx);
|
||||
sc->rx_in_progress = 1;
|
||||
sc->pci_vtnet_rx(sc);
|
||||
sc->rx_in_progress = 0;
|
||||
pthread_mutex_unlock(&sc->rx_mtx);
|
||||
|
||||
}
|
||||
@ -921,7 +895,6 @@ pci_vtnet_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
|
||||
|
||||
sc->rx_merge = 1;
|
||||
sc->rx_vhdrlen = sizeof(struct virtio_net_rxhdr);
|
||||
sc->rx_in_progress = 0;
|
||||
pthread_mutex_init(&sc->rx_mtx, NULL);
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user