code: func (r *rx) postAndReceive(b []queue.RxBuffer, stopRequested *uint32) ([]queue.RxBuffer, uint32) {
  	// Post the buffers first. If we cannot post, sleep until we can. We
  	// never post more than will fit concurrently, so it's safe to wait
  	// until enough room is available.
  	if len(b) != 0 && !r.q.PostBuffers(b) {
  		r.q.EnableNotification()
  		for !r.q.PostBuffers(b) {
  			var tmp [8]byte
  			rawfile.BlockingRead(r.eventFD, tmp[:])
  			if atomic.LoadUint32(stopRequested) != 0 {
  				r.q.DisableNotification()
  				return nil, 0
  			}
  		}
  		r.q.DisableNotification()
  	}
  
  	// Read the next set of descriptors.
  	b, n := r.q.Dequeue(b[:0])
  	if len(b) != 0 {
  		return b, n
  	}
  
  	// Data isn't immediately available. Enable eventfd notifications.
  	r.q.EnableNotification()
  	for {
  		b, n = r.q.Dequeue(b)
  		if len(b) != 0 {
  			break
  		}
  
  		// Wait for notification.
  		var tmp [8]byte
  		rawfile.BlockingRead(r.eventFD, tmp[:])
  		if atomic.LoadUint32(stopRequested) != 0 {
  			r.q.DisableNotification()
  			return nil, 0
  		}
  	}
  	r.q.DisableNotification()
  
  	return b, n
  }
docs: // postAndReceive posts the provided buffers (if any), and then tries to read
  // from the receive queue.
  //
  // Capacity permitting, it reuses the posted buffer slice to store the buffers
  // that were read as well.
  //
  // This function will block if there aren't any available packets.