/** * Compiler barrier. * * Guarantees that operation reordering does not occur at compile time * for operations directly before and after the barrier.
*/ #define rte_compiler_barrier() ({ asmvolatile ("" : : : "memory"); })
/* * 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
*/ staticint
vmbus_txbr_write(struct vmbus_br *tbr, conststruct iovec iov[], int iovlen)
{ 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;
/* 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 */ if (windex != next_windex) return -EINVAL;
/* Ensure that data is available before updating host index */
rte_compiler_barrier();
/* Checkin for our reservation. wait for our turn to update host */ while (!rte_atomic32_cmpset(&vbr->windex, old_windex, next_windex))
_mm_pause();
/* Copy data from receive ring but don't change index */ staticint
vmbus_rxbr_peek(conststruct vmbus_br *rbr, void *data, size_t dlen)
{
uint32_t avail;
/* * The requested data and the 64bits channel packet * offset should be there at least.
*/
avail = vmbus_br_availread(rbr); if (avail < dlen + sizeof(uint64_t)) return -EAGAIN;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.