Listing 3

#include "fifo.h"

/* Initialization */
static inline
void pktq_init (FIFO_T *q, FIFO_CELL_T *base, int size) {
  volatile FIFO_CELL_T *ptr;
  int n;

  FIFO_INIT (q, base, size);
  for (ptr = q->head.l, n = size; n--; ptr++) *ptr = NULL;
}

/* Producers */
static inline
FIFO_CELL_T *pktq_ins_valid (FIFO_T *q, FIFO_SIZE_T n) {
  FIFO_SIZE_T avail = FIFO_AVAIL (q);

  if (n != 0 && ((n < 0 && n >= avail - q->size + 2)
                 || n <= avail))
  {
    volatile FIFO_CELL_T *ptr = q->tail.l + n - 1;
    ptr = CIRC_ARR_WRAP (ptr, q->base, q->end, q->size);
    if (*ptr == NULL) return (FIFO_CELL_T *) ptr;
  }

  return NULL;
}

static inline void pktq_ins_at (FIFO_T *q, int n,
  FIFO_CELL_T pkt, volatile FIFO_CELL_T *ptr)
{
  *ptr = pkt;
  if (n > 0)
    q->tail.w = CIRC_ARR_ADV_PTR (ptr, q->base, q->end);
}

static inline
void pktq_ins_oo (FIFO_T *q, int n, FIFO_CELL_T pkt) {
  int len = FIFO_USED (q);
  volatile FIFO_CELL_T *ptr = q->tail.l + n - 1;

  ptr = CIRC_ARR_WRAP (ptr, q->base, q->end, q->size);
  pktq_ins_at (q, n, pkt, ptr);
}

/* Consumers */
STATIC_INLINE void pktq_drop (FIFO_T *q, FIFO_SIZE_T n) {
  FIFO_SIZE_T total;
  volatile FIFO_CELL_T *ptr;

  for (ptr = q->head.l, total = 0; n;
       ptr = CIRC_ARR_ADV_PTR (ptr, q->base, q->end), total++)
    if (ptr == q->tail.r) break;
    else if (*ptr) { *ptr = NULL; n--; }
  FIFO_DROP (q, total);
}

static inline FIFO_CELL_T pktq_read (FIFO_T *q) {
  FIFO_CELL_T result = NULL;
  FIFO_SIZE_T total;
  volatile FIFO_CELL_T *ptr;

  for (ptr = q->head.l, total = 0; ptr != q->tail.r;
       ptr = CIRC_ARR_ADV_PTR (ptr, q->base, q->end), total++)
    if (*ptr) {
      result = *ptr; *ptr = NULL; total++;
      break;
    }

  FIFO_DROP (q, total);
  return result;
}