All of lore.kernel.org
 help / color / mirror / Atom feed
From: Beniamino Galvani <b.galvani@gmail.com>
To: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Cc: "Peter Maydell" <peter.maydell@linaro.org>,
	"Andreas Färber" <afaerber@suse.de>,
	"QEMU Developers" <qemu-devel@nongnu.org>,
	"Li Guang" <lig.fnst@cn.fujitsu.com>,
	"Stefan Hajnoczi" <stefanha@gmail.com>
Subject: Re: [Qemu-devel] [PATCH v4 1/3] util/fifo8: implement push/pop of multiple bytes
Date: Tue, 28 Jan 2014 19:44:34 +0100	[thread overview]
Message-ID: <20140128184401.GA4660@gmail.com> (raw)
In-Reply-To: <CAEgOgz5KgpgETcK_4YNX5_vXq7cNZXWvvpKnMr=K4zA5TLLfZA@mail.gmail.com>

On Tue, Jan 28, 2014 at 10:04:09AM +1000, Peter Crosthwaite wrote:
> On Tue, Jan 28, 2014 at 4:32 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> > On 26 January 2014 21:39, Beniamino Galvani <b.galvani@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.galvani@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.
> >
> 
> No bug - where the ring buffer starts following a reset is undefined
> and need not be defined. But it improves the predicatability of the
> newly added pop_buf fn as you can now following a reset, guarantee
> that a single pop_buf will take all contents if its the first pop
> (which is how its being used in P2).

Right; in the next patch I will add an explanation.
 
> >>  }
> >>
> >>  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);
> >> +}
> >> +
> 
> This is a little specific and perhaps limited in usage. Can we just
> add occupancy/vacancy getters and let the caller do what it wants:
> 
> uint32_t fifo8_num_free(Fifo *fifo) {
>     return fifo->capacity - fifo->num;
> }

Ok.

Thanks,
Beniamino

  parent reply	other threads:[~2014-01-28 18:45 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-01-26 21:39 [Qemu-devel] [PATCH v4 0/3] hw/arm: add ethernet support to Allwinner A10 Beniamino Galvani
2014-01-26 21:39 ` [Qemu-devel] [PATCH v4 1/3] util/fifo8: implement push/pop of multiple bytes Beniamino Galvani
2014-01-27 18:32   ` Peter Maydell
2014-01-28  0:04     ` Peter Crosthwaite
2014-01-28 10:43       ` Peter Maydell
2014-01-28 18:48         ` Beniamino Galvani
2014-01-29 12:02           ` Peter Crosthwaite
2014-01-28 18:44       ` Beniamino Galvani [this message]
2014-01-26 21:39 ` [Qemu-devel] [PATCH v4 2/3] hw/net: add support for Allwinner EMAC Fast Ethernet controller Beniamino Galvani
2014-01-27 18:41   ` Peter Maydell
2014-01-28  0:31   ` Peter Crosthwaite
2014-01-26 21:39 ` [Qemu-devel] [PATCH v4 3/3] hw/arm/allwinner-a10: initialize EMAC Beniamino Galvani
2014-01-27 18:44   ` Peter Maydell
2014-01-28  0:32   ` Peter Crosthwaite

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20140128184401.GA4660@gmail.com \
    --to=b.galvani@gmail.com \
    --cc=afaerber@suse.de \
    --cc=lig.fnst@cn.fujitsu.com \
    --cc=peter.crosthwaite@xilinx.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.