mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-28 02:35:28 +00:00
These versions of the queue add and remove methods support using memcpy like routines to access regions of memory with specific requirements. In particular, this will allow for transfers between queues and USB packet RAM on the STM32 which has specific access requirements. This change also includes an update to the mem* util routines to make their prototypes compatible with C89 and POSIX standards. Signed-off-by: Anton Staaf <robotboy@chromium.org> BRANCH=None BUG=None TEST=make buildall -j Test USB Echo functionality on discovery-stm32f072 board to ensure that queues still function correctly. Change-Id: I557064d99abfc3e8cfc98099a1d94334a976550c Reviewed-on: https://chromium-review.googlesource.com/239217 Tested-by: Anton Staaf <robotboy@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org> Commit-Queue: Anton Staaf <robotboy@chromium.org> Trybot-Ready: Anton Staaf <robotboy@chromium.org>
155 lines
3.3 KiB
C
155 lines
3.3 KiB
C
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*
|
|
* Queue data structure implementation.
|
|
*/
|
|
#include "queue.h"
|
|
#include "util.h"
|
|
|
|
void queue_init(struct queue const *q)
|
|
{
|
|
ASSERT(POWER_OF_TWO(q->buffer_units));
|
|
|
|
q->state->head = 0;
|
|
q->state->tail = 0;
|
|
}
|
|
|
|
int queue_is_empty(struct queue const *q)
|
|
{
|
|
return q->state->head == q->state->tail;
|
|
}
|
|
|
|
size_t queue_count(struct queue const *q)
|
|
{
|
|
return q->state->tail - q->state->head;
|
|
}
|
|
|
|
size_t queue_space(struct queue const *q)
|
|
{
|
|
return q->buffer_units - queue_count(q);
|
|
}
|
|
|
|
size_t queue_add_unit(struct queue const *q, void const *src)
|
|
{
|
|
size_t tail = q->state->tail & (q->buffer_units - 1);
|
|
|
|
if (queue_space(q) == 0)
|
|
return 0;
|
|
|
|
if (q->unit_bytes == 1)
|
|
q->buffer[tail] = *((uint8_t *) src);
|
|
else
|
|
memcpy(q->buffer + tail * q->unit_bytes, src, q->unit_bytes);
|
|
|
|
q->state->tail += 1;
|
|
|
|
return 1;
|
|
}
|
|
|
|
size_t queue_add_units(struct queue const *q, void const *src, size_t count)
|
|
{
|
|
return queue_add_memcpy(q, src, count, memcpy);
|
|
}
|
|
|
|
size_t queue_add_memcpy(struct queue const *q,
|
|
void const *src,
|
|
size_t count,
|
|
void *(*memcpy)(void *dest,
|
|
void const *src,
|
|
size_t n))
|
|
{
|
|
size_t transfer = MIN(count, queue_space(q));
|
|
size_t tail = q->state->tail & (q->buffer_units - 1);
|
|
size_t first = MIN(transfer, q->buffer_units - tail);
|
|
|
|
memcpy(q->buffer + tail * q->unit_bytes,
|
|
src,
|
|
first * q->unit_bytes);
|
|
|
|
if (first < transfer)
|
|
memcpy(q->buffer,
|
|
((uint8_t const *) src) + first * q->unit_bytes,
|
|
(transfer - first) * q->unit_bytes);
|
|
|
|
q->state->tail += transfer;
|
|
|
|
return transfer;
|
|
}
|
|
|
|
static void queue_read_safe(struct queue const *q,
|
|
void *dest,
|
|
size_t head,
|
|
size_t transfer,
|
|
void *(*memcpy)(void *dest,
|
|
void const *src,
|
|
size_t n))
|
|
{
|
|
size_t first = MIN(transfer, q->buffer_units - head);
|
|
|
|
memcpy(dest,
|
|
q->buffer + head * q->unit_bytes,
|
|
first * q->unit_bytes);
|
|
|
|
if (first < transfer)
|
|
memcpy(((uint8_t *) dest) + first * q->unit_bytes,
|
|
q->buffer,
|
|
(transfer - first) * q->unit_bytes);
|
|
}
|
|
|
|
size_t queue_remove_unit(struct queue const *q, void *dest)
|
|
{
|
|
size_t head = q->state->head & (q->buffer_units - 1);
|
|
|
|
if (queue_count(q) == 0)
|
|
return 0;
|
|
|
|
if (q->unit_bytes == 1)
|
|
*((uint8_t *) dest) = q->buffer[head];
|
|
else
|
|
memcpy(dest, q->buffer + head * q->unit_bytes, q->unit_bytes);
|
|
|
|
q->state->head += 1;
|
|
|
|
return 1;
|
|
}
|
|
|
|
size_t queue_remove_units(struct queue const *q, void *dest, size_t count)
|
|
{
|
|
return queue_remove_memcpy(q, dest, count, memcpy);
|
|
}
|
|
|
|
size_t queue_remove_memcpy(struct queue const *q,
|
|
void *dest,
|
|
size_t count,
|
|
void *(*memcpy)(void *dest,
|
|
void const *src,
|
|
size_t n))
|
|
{
|
|
size_t transfer = MIN(count, queue_count(q));
|
|
size_t head = q->state->head & (q->buffer_units - 1);
|
|
|
|
queue_read_safe(q, dest, head, transfer, memcpy);
|
|
|
|
q->state->head += transfer;
|
|
|
|
return transfer;
|
|
}
|
|
|
|
size_t queue_peek_units(struct queue const *q,
|
|
void *dest,
|
|
size_t i,
|
|
size_t count)
|
|
{
|
|
size_t available = queue_count(q);
|
|
size_t transfer = MIN(count, available - i);
|
|
|
|
if (i < available) {
|
|
size_t head = (q->state->head + i) & (q->buffer_units - 1);
|
|
|
|
queue_read_safe(q, dest, head, transfer, memcpy);
|
|
}
|
|
|
|
return transfer;
|
|
}
|