Fix hang in virtio_driver::wait_for_queue
virtio_driver::wait_for_queue() would often hang in a memcached and mc_benchmark workload, waiting forever for received packets although these *do* arrive. As part of the virtio protocol, we need to set the host notification flag (we call this, somewhat confusingly, queue->enable_interrupts()) and then check if there's anything in the queue, and if not, wait for the interrupt. This order is important: If we check the queue and only then set the notification flag, and data came in between those, the check will be empty and an interrupt never sent - and we can wait indefinitely for data that has already arrived. We did this in the right order, but the host code, running on a different CPU, might see memory accesses in a different order! We need a memory fence to ensure that the same order is also seen on other processors. This patch adds a memory fence to the end of the enable_interrupts() function itself, so we can continue to use it as before in wait_for_queue(). Note that we do *not* add a memory fence to disable_interrupts() - because no current use (and no expected use) cares about the ordering of disable_interrupts() vs other memory accesses.
Please register or sign in to comment