On 26 January 2014 21:39, Beniamino Galvani <b.galv...@gmail.com> wrote: > In some circumstances it is useful to be able to push the entire > content of a memory buffer to the fifo or to pop multiple bytes with a > single operation. > > The functions fifo8_has_space() and fifo8_push_all() added by this > patch allow to perform the first kind of operation efficiently. > > The function fifo8_pop_buf() can be used instead to pop multiple bytes > from the fifo, returning a pointer to the backing buffer.
Thanks; a few nits below but mostly this looks OK. > Signed-off-by: Beniamino Galvani <b.galv...@gmail.com> > --- > include/qemu/fifo8.h | 43 +++++++++++++++++++++++++++++++++++++++++++ > util/fifo8.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 87 insertions(+) > > diff --git a/include/qemu/fifo8.h b/include/qemu/fifo8.h > index d318f71..ea6e9f6 100644 > --- a/include/qemu/fifo8.h > +++ b/include/qemu/fifo8.h > @@ -44,6 +44,19 @@ void fifo8_destroy(Fifo8 *fifo); > void fifo8_push(Fifo8 *fifo, uint8_t data); > > /** > + * fifo8_push_all: > + * @fifo: FIFO to push to > + * @data: data to push > + * @size: number of bytes to push > + * > + * Push a byte array to the FIFO. Behaviour is undefined is the FIFO is "if the FIFO" > + * full. Clients are responsible for checking the space left in the FIFO > using > + * fifo8_has_space(). > + */ > + > +void fifo8_push_all(Fifo8 *fifo, const uint8_t *data, uint32_t num); > + > +/** > * fifo8_pop: > * @fifo: fifo to pop from > * > @@ -56,6 +69,24 @@ void fifo8_push(Fifo8 *fifo, uint8_t data); > uint8_t fifo8_pop(Fifo8 *fifo); > > /** > + * fifo8_pop_buf: > + * @fifo: FIFO to pop from > + * @max: maximum number of bytes to pop > + * @num: actual number of returned bytes > + * > + * Pop a number of elements from the FIFO up to a maximum of max. The buffer > + * containing the popped data is returned. This buffer points directly into > + * the FIFO backing store and data is invalidated once any of the fifo8_* > APIs > + * are called on the FIFO. > + * > + * May short return, the number of valid bytes returned is populated in > + * *num. Will always return at least 1 byte. What does "May short return" mean here? Rephrasing might help. Like fifo8_pop, you should say that clients are responsible for checking that the fifo is empty before calling this. > + * > + * Behavior is undefined if max == 0. > + */ > +const uint8_t *fifo8_pop_buf(Fifo8 *fifo, uint32_t max, uint32_t *num); > + > +/** > * fifo8_reset: > * @fifo: FIFO to reset > * > @@ -86,6 +117,18 @@ bool fifo8_is_empty(Fifo8 *fifo); > > bool fifo8_is_full(Fifo8 *fifo); > > +/** > + * fifo8_has_space: > + * @fifo: FIFO to check > + * @num: number of bytes > + * > + * Check if a given number of bytes can be pushed to a FIFO. > + * > + * Returns: True if the fifo can hold the given elements, false otherwise. > + */ > + > +bool fifo8_has_space(Fifo8 *fifo, uint32_t num); > + > extern const VMStateDescription vmstate_fifo8; > > #define VMSTATE_FIFO8(_field, _state) { \ > diff --git a/util/fifo8.c b/util/fifo8.c > index 013e903..2808169 100644 > --- a/util/fifo8.c > +++ b/util/fifo8.c > @@ -15,6 +15,8 @@ > #include "qemu-common.h" > #include "qemu/fifo8.h" > > +#define min(a, b) ((a) < (b) ? (a) : (b)) Just use MIN, the QEMU include files define it for you. > void fifo8_create(Fifo8 *fifo, uint32_t capacity) > { > fifo->data = g_new(uint8_t, capacity); > @@ -37,6 +39,27 @@ void fifo8_push(Fifo8 *fifo, uint8_t data) > fifo->num++; > } > > +void fifo8_push_all(Fifo8 *fifo, const uint8_t *data, uint32_t num) > +{ > + uint32_t start, avail; > + > + if (fifo->num + num > fifo->capacity) { > + abort(); > + } > + > + start = (fifo->head + fifo->num) % fifo->capacity; > + > + if (start + num <= fifo->capacity) { > + memcpy(&fifo->data[start], data, num); > + } else { > + avail = fifo->capacity - start; > + memcpy(&fifo->data[start], data, avail); > + memcpy(&fifo->data[0], &data[avail], num - avail); > + } > + > + fifo->num += num; > +} > + > uint8_t fifo8_pop(Fifo8 *fifo) > { > uint8_t ret; > @@ -50,9 +73,25 @@ uint8_t fifo8_pop(Fifo8 *fifo) > return ret; > } > > +const uint8_t *fifo8_pop_buf(Fifo8 *fifo, uint32_t max, uint32_t *num) > +{ > + uint8_t *ret; > + > + *num = min(fifo->capacity - fifo->head, max); > + *num = min(*num, fifo->num); > + > + ret = &fifo->data[fifo->head]; > + > + fifo->head += *num; > + fifo->head %= fifo->capacity; > + > + return ret; > +} > + > void fifo8_reset(Fifo8 *fifo) > { > fifo->num = 0; > + fifo->head = 0; This is a bug fix, right? It should go in its own patch. > } > > bool fifo8_is_empty(Fifo8 *fifo) > @@ -65,6 +104,11 @@ bool fifo8_is_full(Fifo8 *fifo) > return (fifo->num == fifo->capacity); > } > > +bool fifo8_has_space(Fifo8 *fifo, uint32_t num) > +{ > + return (fifo->num + num <= fifo->capacity); > +} > + > const VMStateDescription vmstate_fifo8 = { > .name = "Fifo8", > .version_id = 1, > -- > 1.7.10.4 > thanks -- PMM