A computer-implemented method comprising: providing a memory block shared between a first endpoint and a second endpoint, the shared memory block including at least one buffer, a post counter, a buffer ownership bitmap having bits identifying ownership of the at least one buffer as between the first endpoint and the second endpoint, and an acknowledgment counter, and the first endpoint being one of a host for a virtual machine hosted by a computing device or the virtual machine, and the second endpoint being one of the host or another virtual machine hosted by the computing device; sending, by the first endpoint, data to the second endpoint, the sending including: identifying, based on the buffer ownership bit map, one of the at least one buffer as being currently owned by the first endpoint and storing data in that buffer; detecting that the acknowledgment counter is equal to the post counter; and following detecting that the acknowledgment counter is equal to the post counter, incrementing the post counter to signal that data has been stored for receipt by the second endpoint; receiving, by the second endpoint, the data from the first endpoint, the receiving including: detecting that the post counter has changed; and following detecting that the post counter has changed, incrementing the acknowledgment counter to acknowledge receipt of the data. wherein prior to incrementing the acknowledgment counter, taking, by the second endpoint, ownership of the one of the at least one buffer by toggling the value of a bit of the buffer ownership bitmap corresponding to that buffer; and wherein: the second endpoint: after taking ownership of the one of the at least one buffer, processing the data stored in that buffer; and after completing processing of the data stored in the one of the at least one buffer, releasing ownership of the one of the at least one buffer to the first endpoint by toggling the value of the bit of the buffer ownership bitmap corresponding to that buffer. providing a memory block shared between a first endpoint and a second endpoint, the shared memory block including at least one buffer, a post counter, a buffer ownership bitmap having bits identifying ownership of the at least one buffer as between the first endpoint and the second endpoint, and an acknowledgment counter, and the first endpoint being one of a host for a virtual machine hosted by a computing device or the virtual machine, and the second endpoint being one of the host or another virtual machine hosted by the computing device; sending, by the first endpoint, data to the second endpoint, the sending including: identifying, based on the buffer ownership bit map, one of the at least one buffer as being currently owned by the first endpoint and storing data in that buffer; detecting that the acknowledgment counter is equal to the post counter; and following detecting that the acknowledgment counter is equal to the post counter, incrementing the post counter to signal that data has been stored for receipt by the second endpoint; identifying, based on the buffer ownership bit map, one of the at least one buffer as being currently owned by the first endpoint and storing data in that buffer; detecting that the acknowledgment counter is equal to the post counter; and following detecting that the acknowledgment counter is equal to the post counter, incrementing the post counter to signal that data has been stored for receipt by the second endpoint; receiving, by the second endpoint, the data from the first endpoint, the receiving including: detecting that the post counter has changed; and following detecting that the post counter has changed, incrementing the acknowledgment counter to acknowledge receipt of the data. detecting that the post counter has changed; and following detecting that the post counter has changed, incrementing the acknowledgment counter to acknowledge receipt of the data. wherein prior to incrementing the acknowledgment counter, taking, by the second endpoint, ownership of the one of the at least one buffer by toggling the value of a bit of the buffer ownership bitmap corresponding to that buffer; and wherein: the second endpoint: after taking ownership of the one of the at least one buffer, processing the data stored in that buffer; and after completing processing of the data stored in the one of the at least one buffer, releasing ownership of the one of the at least one buffer to the first endpoint by toggling the value of the bit of the buffer ownership bitmap corresponding to that buffer. after taking ownership of the one of the at least one buffer, processing the data stored in that buffer; and after completing processing of the data stored in the one of the at least one buffer, releasing ownership of the one of the at least one buffer to the first endpoint by toggling the value of the bit of the buffer ownership bitmap corresponding to that buffer.