zephyr/kernel/unified/ring_buffer.c
Kumar Gala d12d8af186 unified: move code from nanokernel into unified kernel
As the unified kernel should replace the nanokernel and microkernel
lets go ahead and move code shared between the nanonkernel and unified
kernel into the unified kernel.

Change-Id: I8931efa5d67025381d5d0d9563e7c6632cece87f
Signed-off-by: Kumar Gala <kumar.gala@linaro.org>
2016-10-10 00:46:40 +00:00

106 lines
2.7 KiB
C

/* ring_buffer.c: Simple ring buffer API */
/*
* Copyright (c) 2015 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <misc/ring_buffer.h>
/**
* Internal data structure for a buffer header.
*
* We want all of this to fit in a single uint32_t. Every item stored in the
* ring buffer will be one of these headers plus any extra data supplied
*/
struct ring_element {
uint32_t type :16; /**< Application-specific */
uint32_t length :8; /**< length in 32-bit chunks */
uint32_t value :8; /**< Room for small integral values */
};
int sys_ring_buf_put(struct ring_buf *buf, uint16_t type, uint8_t value,
uint32_t *data, uint8_t size32)
{
uint32_t i, space, index, rc;
space = sys_ring_buf_space_get(buf);
if (space >= (size32 + 1)) {
struct ring_element *header =
(struct ring_element *)&buf->buf[buf->tail];
header->type = type;
header->length = size32;
header->value = value;
if (likely(buf->mask)) {
for (i = 0; i < size32; ++i) {
index = (i + buf->tail + 1) & buf->mask;
buf->buf[index] = data[i];
}
buf->tail = (buf->tail + size32 + 1) & buf->mask;
} else {
for (i = 0; i < size32; ++i) {
index = (i + buf->tail + 1) % buf->size;
buf->buf[index] = data[i];
}
buf->tail = (buf->tail + size32 + 1) % buf->size;
}
rc = 0;
} else {
buf->dropped_put_count++;
rc = -EMSGSIZE;
}
return rc;
}
int sys_ring_buf_get(struct ring_buf *buf, uint16_t *type, uint8_t *value,
uint32_t *data, uint8_t *size32)
{
struct ring_element *header;
uint32_t i, index;
if (sys_ring_buf_is_empty(buf)) {
return -EAGAIN;
}
header = (struct ring_element *) &buf->buf[buf->head];
if (header->length > *size32) {
*size32 = header->length;
return -EMSGSIZE;
}
*size32 = header->length;
*type = header->type;
*value = header->value;
if (likely(buf->mask)) {
for (i = 0; i < header->length; ++i) {
index = (i + buf->head + 1) & buf->mask;
data[i] = buf->buf[index];
}
buf->head = (buf->head + header->length + 1) & buf->mask;
} else {
for (i = 0; i < header->length; ++i) {
index = (i + buf->head + 1) % buf->size;
data[i] = buf->buf[index];
}
buf->head = (buf->head + header->length + 1) % buf->size;
}
return 0;
}