src/dpdk/drivers/bus/vmbus/vmbus_bufring.c
int
vmbus_txbr_write(struct vmbus_br *tbr, const struct iovec iov[], int iovlen,
		 bool *need_sig)
{
	struct vmbus_bufring *vbr = tbr->vbr;
	uint32_t ring_size = tbr->dsize;
	uint32_t old_windex, next_windex, windex, total;
	uint64_t save_windex;
	int i;

	total = 0;
	for (i = 0; i < iovlen; i++)
		total += iov[i].iov_len;
	total += sizeof(save_windex);

	/* Reserve space in ring */
	do {
		uint32_t avail;

		/* Get current free location */
		old_windex = tbr->windex;

		/* Prevent compiler reordering this with calculation */
		rte_compiler_barrier();

		avail = vmbus_br_availwrite(tbr, old_windex);

		/* If not enough space in ring, then tell caller. */
		if (avail <= total)
			return -EAGAIN;

		next_windex = vmbus_br_idxinc(old_windex, total, ring_size);

		/* Atomic update of next write_index for other threads */
	} while (!rte_atomic32_cmpset(&tbr->windex, old_windex, next_windex));

	/* Space from old..new is now reserved */
	windex = old_windex;
	for (i = 0; i < iovlen; i++) {
		windex = vmbus_txbr_copyto(tbr, windex,
					   iov[i].iov_base, iov[i].iov_len);
	}

	/* Set the offset of the current channel packet. */
	save_windex = ((uint64_t)old_windex) << 32;
	windex = vmbus_txbr_copyto(tbr, windex, &save_windex,
				   sizeof(save_windex));

	/* The region reserved should match region used */
	RTE_ASSERT(windex == next_windex);

	/* Ensure that data is available before updating host index */
	rte_smp_wmb();

	/* Checkin for our reservation. wait for our turn to update host */
	while (!rte_atomic32_cmpset(&vbr->windex, old_windex, next_windex))
		rte_pause();

	/* If host had read all data before this, then need to signal */
	*need_sig |= vmbus_txbr_need_signal(vbr, old_windex);
	return 0;
}
/*
 * Write scattered channel packet to TX bufring.
 *
 * The offset of this channel packet is written as a 64bits value
 * immediately after this channel packet.
 *
 * The write goes through three stages:
 *  1. Reserve space in ring buffer for the new data.
 *     Writer atomically moves priv_write_index.
 *  2. Copy the new data into the ring.
 *  3. Update the tail of the ring (visible to host) that indicates
 *     next read location. Writer updates write_index
 */
Write scattered channel packet to TX bufring.
The offset of this channel packet is written as a 64bits value
immediately after this channel packet.

The write goes through three stages:
1. Reserve space in ring buffer for the new data.
Writer atomically moves priv_write_index.
2. Copy the new data into the ring.
3. Update the tail of the ring (visible to host) that indicates
next read location.
Write scattered channel packet to TX bufring . The offset of this channel packet is written as a 64bits value immediately after this channel packet . The write goes through three stages : 1 . Reserve space in ring buffer for the new data . Writer atomically moves priv_write_index . 2 . Copy the new data into the ring . 3 . Update the tail of the ring ( visible to host ) that indicates next read location .
int
vmbus_txbr_write(struct vmbus_br *tbr, const struct iovec iov[], int iovlen,
		 bool *need_sig)
{
	struct vmbus_bufring *vbr = tbr->vbr;
	uint32_t ring_size = tbr->dsize;
	uint32_t old_windex, next_windex, windex, total;
	uint64_t save_windex;
	int i;
	total = 0;
	for (i = 0; i < iovlen; i++)
		total += iov[i].iov_len;
	total += sizeof(save_windex);
	do {
		uint32_t avail;
		old_windex = tbr->windex;
		rte_compiler_barrier();
		avail = vmbus_br_availwrite(tbr, old_windex);
		if (avail <= total)
			return -EAGAIN;
		next_windex = vmbus_br_idxinc(old_windex, total, ring_size);
	} while (!rte_atomic32_cmpset(&tbr->windex, old_windex, next_windex));
	windex = old_windex;
	for (i = 0; i < iovlen; i++) {
		windex = vmbus_txbr_copyto(tbr, windex,
					   iov[i].iov_base, iov[i].iov_len);
	}
	save_windex = ((uint64_t)old_windex) << 32;
	windex = vmbus_txbr_copyto(tbr, windex, &save_windex,
				   sizeof(save_windex));
	RTE_ASSERT(windex == next_windex);
	rte_smp_wmb();
	while (!rte_atomic32_cmpset(&vbr->windex, old_windex, next_windex))
		rte_pause();
	*need_sig |= vmbus_txbr_need_signal(vbr, old_windex);
	return 0;
}
int vmbus_txbr_write ( struct vmbus_br * tbr , const struct iovec iov [ ] , int iovlen , bool * need_sig ) { struct vmbus_bufring * vbr = tbr -> vbr ; uint32_t ring_size = tbr -> dsize ; uint32_t old_windex , next_windex , windex , total ; uint64_t save_windex ; int i ; total = 0 ; for ( i = 0 ; i < iovlen ; i ++ ) total += iov [ i ] . iov_len ; total += sizeof ( save_windex ) ; do { uint32_t avail ; old_windex = tbr -> windex ; rte_compiler_barrier ( ) ; avail = vmbus_br_availwrite ( tbr , old_windex ) ; if ( avail <= total ) return - EAGAIN ; next_windex = vmbus_br_idxinc ( old_windex , total , ring_size ) ; } while ( ! rte_atomic32_cmpset ( & tbr -> windex , old_windex , next_windex ) ) ; windex = old_windex ; for ( i = 0 ; i < iovlen ; i ++ ) { windex = vmbus_txbr_copyto ( tbr , windex , iov [ i ] . iov_base , iov [ i ] . iov_len ) ; } save_windex = ( ( uint64_t ) old_windex ) << 32 ; windex = vmbus_txbr_copyto ( tbr , windex , & save_windex , sizeof ( save_windex ) ) ; RTE_ASSERT ( windex == next_windex ) ; rte_smp_wmb ( ) ; while ( ! rte_atomic32_cmpset ( & vbr -> windex , old_windex , next_windex ) ) rte_pause ( ) ; * need_sig |= vmbus_txbr_need_signal ( vbr , old_windex ) ; return 0 ; }
Write scattered channel packet to TX bufring.
Write scattered channel packet to TX bufring .
/* Reserve space in ring */ /* Get current free location */ /* Prevent compiler reordering this with calculation */ /* If not enough space in ring, then tell caller. */ /* Atomic update of next write_index for other threads */ /* Space from old..new is now reserved */ /* Set the offset of the current channel packet. */ /* The region reserved should match region used */ /* Ensure that data is available before updating host index */ /* Checkin for our reservation. wait for our turn to update host */ /* If host had read all data before this, then need to signal */