From: Kevin Traynor Date: Thu, 23 Mar 2017 15:44:58 +0000 (+0000) Subject: vhost: fix false sharing X-Git-Tag: spdx-start~3907 X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=4e9474141e1115a3089896848f92b25b53cddfd9;p=dpdk.git vhost: fix false sharing The broadcast_rarp field in the virtio_net struct is checked in the dequeue datapath regardless of whether descriptors are available or not. As it is checked with cmpset leading to a write, false sharing on the virtio_net struct can happen between enqueue and dequeue datapaths regardless of whether a RARP is requested. In OVS, the issue can cause a uni-directional performance drop of up to 15%. Fix that by only performing the cmpset if a read of broadcast_rarp indicates that the cmpset is likely to succeed. Fixes: a66bcad32240 ("vhost: arrange struct fields for better cache sharing") Cc: stable@dpdk.org Signed-off-by: Kevin Traynor Reviewed-by: Maxime Coquelin Acked-by: Yuanhan Liu --- diff --git a/lib/librte_vhost/virtio_net.c b/lib/librte_vhost/virtio_net.c index 337470d64a..d0a3b11131 100644 --- a/lib/librte_vhost/virtio_net.c +++ b/lib/librte_vhost/virtio_net.c @@ -1056,9 +1056,21 @@ rte_vhost_dequeue_burst(int vid, uint16_t queue_id, * array, to looks like that guest actually send such packet. * * Check user_send_rarp() for more information. + * + * broadcast_rarp shares a cacheline in the virtio_net structure + * with some fields that are accessed during enqueue and + * rte_atomic16_cmpset() causes a write if using cmpxchg. This could + * result in false sharing between enqueue and dequeue. + * + * Prevent unnecessary false sharing by reading broadcast_rarp first + * and only performing cmpset if the read indicates it is likely to + * be set. */ - if (unlikely(rte_atomic16_cmpset((volatile uint16_t *) - &dev->broadcast_rarp.cnt, 1, 0))) { + + if (unlikely(rte_atomic16_read(&dev->broadcast_rarp) && + rte_atomic16_cmpset((volatile uint16_t *) + &dev->broadcast_rarp.cnt, 1, 0))) { + rarp_mbuf = rte_pktmbuf_alloc(mbuf_pool); if (rarp_mbuf == NULL) { RTE_LOG(ERR, VHOST_DATA,