#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include "packet_io.h"
#include "packet_utils.h"
#include "packet_queue.h"
struct packet_queue
{
uint64_t *queue;
uint32_t size;
uint32_t head;
uint32_t tail;
};
struct packet_queue *packet_queue_new(uint32_t size)
struct packet_queue *queue = (struct packet_queue *)calloc(1, sizeof(struct packet_queue));
if (queue == NULL)
PACKET_IO_LOG_ERROR("unable to alloc packet queue");
return NULL;
}
queue->queue = (uint64_t *)calloc(size, sizeof(uint64_t));
if (queue->queue == NULL)
PACKET_IO_LOG_ERROR("unable to alloc packet queue buffer");
free(queue);
queue->size = size;
queue->head = 0;
queue->tail = 0;
return queue;
void packet_queue_free(struct packet_queue *queue)
return;
struct packet *pkt = NULL;
while (1)
packet_queue_pop(queue, &pkt);
if (pkt == NULL)
break;
packet_free(pkt);
if (queue->queue)
free(queue->queue);
queue->queue = NULL;
void packet_queue_push(struct packet_queue *queue, struct packet *pkt)
uint64_t wait = 1000;
retry:
if (__sync_val_compare_and_swap(&queue->queue[queue->tail], 0, pkt) != 0)
PACKET_IO_LOG_ERROR("packet queue is full, retry later");
usleep(wait);
wait *= 2;
goto retry;
queue->tail = (queue->tail + 1) % queue->size;
void packet_queue_pop(struct packet_queue *queue, struct packet **pkt)
uint64_t read = ATOMIC_READ(&queue->queue[queue->head]);
if (read == 0)
*pkt = NULL;
__sync_val_compare_and_swap(&queue->queue[queue->head], read, 0);
*pkt = (struct packet *)read;
queue->head = (queue->head + 1) % queue->size;