mirror of
https://github.com/apache/nuttx.git
synced 2026-06-06 08:36:24 +08:00
mm/circ-buf: support circular buffer managerment
N/A Change-Id: I3f996639a51c60d095e292fc43981e4da9929092 Signed-off-by: dongjiuzhu <dongjiuzhu1@xiaomi.com>
This commit is contained in:
@@ -0,0 +1,308 @@
|
||||
/****************************************************************************
|
||||
* include/nuttx/mm/circ_buf.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __INCLUDE_NUTTX_MM_CIRC_BUF_H
|
||||
#define __INCLUDE_NUTTX_MM_CIRC_BUF_H
|
||||
|
||||
/* Note about locking: There is no locking required while only one reader
|
||||
* and one writer is using the circular buffer.
|
||||
* For multiple writer and one reader there is only a need to lock the
|
||||
* writer. And vice versa for only one writer and multiple reader there is
|
||||
* only a need to lock the reader.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/* This structure describes circular buffer */
|
||||
|
||||
struct circ_buf_s
|
||||
{
|
||||
FAR void *base; /* The pointer to buffer space */
|
||||
size_t size; /* The size of buffer space */
|
||||
size_t head; /* The head of buffer space */
|
||||
size_t tail; /* The tail of buffer space */
|
||||
bool external; /* The flag for external buffer */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: circ_buf_init
|
||||
*
|
||||
* Description:
|
||||
* Initialize a circular buffer.
|
||||
*
|
||||
* Input Parameters:
|
||||
* circ - Address of the circular buffer to be used.
|
||||
* base - A pointer to circular buffer's internal buffer. It can be
|
||||
* provided by caller because sometimes the creation of buffer
|
||||
* is special or needs to preallocated, eg: DMA buffer.
|
||||
* If NULL, a buffer of the given size will be allocated.
|
||||
* bytes - The size of the internal buffer.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; A negated errno value is returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int circ_buf_init(FAR struct circ_buf_s *circ,
|
||||
FAR void *base, size_t bytes);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: circ_buf_resize
|
||||
*
|
||||
* Description:
|
||||
* Resize a circular buffer (change buffer size).
|
||||
*
|
||||
* Input Parameters:
|
||||
* circ - Address of the circular buffer to be used.
|
||||
* bytes - The size of the internal buffer.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; A negated errno value is returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int circ_buf_resize(FAR struct circ_buf_s *circ, size_t bytes);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: circ_buf_uninit
|
||||
*
|
||||
* Description:
|
||||
* Free the circular buffer.
|
||||
*
|
||||
* Input Parameters:
|
||||
* circ - Address of the circular buffer to be used.
|
||||
****************************************************************************/
|
||||
|
||||
void circ_buf_uninit(FAR struct circ_buf_s *circ);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: circ_buf_reset
|
||||
*
|
||||
* Description:
|
||||
* Remove the entire circular buffer content.
|
||||
*
|
||||
* Input Parameters:
|
||||
* circ - Address of the circular buffer to be used.
|
||||
****************************************************************************/
|
||||
|
||||
void circ_buf_reset(FAR struct circ_buf_s *circ);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: circ_buf_is_full
|
||||
*
|
||||
* Description:
|
||||
* Return true if the circular buffer is full.
|
||||
*
|
||||
* Input Parameters:
|
||||
* circ - Address of the circular buffer to be used.
|
||||
****************************************************************************/
|
||||
|
||||
bool circ_buf_is_full(FAR struct circ_buf_s *circ);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: circ_buf_is_empty
|
||||
*
|
||||
* Description:
|
||||
* Return true if the circular buffer is empty.
|
||||
*
|
||||
* Input Parameters:
|
||||
* circ - Address of the circular buffer to be used.
|
||||
****************************************************************************/
|
||||
|
||||
bool circ_buf_is_empty(FAR struct circ_buf_s *circ);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: circ_buf_size
|
||||
*
|
||||
* Description:
|
||||
* Return size of the circular buffer.
|
||||
*
|
||||
* Input Parameters:
|
||||
* circ - Address of the circular buffer to be used.
|
||||
****************************************************************************/
|
||||
|
||||
size_t circ_buf_size(FAR struct circ_buf_s *circ);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: circ_buf_used
|
||||
*
|
||||
* Description:
|
||||
* Return the used bytes of the circular buffer.
|
||||
*
|
||||
* Input Parameters:
|
||||
* circ - Address of the circular buffer to be used.
|
||||
****************************************************************************/
|
||||
|
||||
size_t circ_buf_used(FAR struct circ_buf_s *circ);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: circ_buf_space
|
||||
*
|
||||
* Description:
|
||||
* Return the remaing space of the circular buffer.
|
||||
*
|
||||
* Input Parameters:
|
||||
* circ - Address of the circular buffer to be used.
|
||||
****************************************************************************/
|
||||
|
||||
size_t circ_buf_space(FAR struct circ_buf_s *circ);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: circ_buf_peek
|
||||
*
|
||||
* Description:
|
||||
* Get data form the circular buffer without removing
|
||||
*
|
||||
* Note :
|
||||
* That with only one concurrent reader and one concurrent writer,
|
||||
* you don't need extra locking to use these api.
|
||||
*
|
||||
* Input Parameters:
|
||||
* circ - Address of the circular buffer to be used.
|
||||
* dst - Address where to store the data.
|
||||
* bytes - Number of bytes to get.
|
||||
*
|
||||
* Returned Value:
|
||||
* The bytes of get data is returned if the peek data is successful;
|
||||
* A negated errno value is returned on any failure.
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t circ_buf_peek(FAR struct circ_buf_s *circ,
|
||||
FAR void *dst, size_t bytes);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: circ_buf_read
|
||||
*
|
||||
* Description:
|
||||
* Get data form the circular buffer.
|
||||
*
|
||||
* Note :
|
||||
* That with only one concurrent reader and one concurrent writer,
|
||||
* you don't need extra locking to use these api.
|
||||
*
|
||||
* Input Parameters:
|
||||
* circ - Address of the circular buffer to be used.
|
||||
* dst - Address where to store the data.
|
||||
* bytes - Number of bytes to get.
|
||||
*
|
||||
* Returned Value:
|
||||
* The bytes of get data is returned if the read data is successful;
|
||||
* A negated errno value is returned on any failure.
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t circ_buf_read(FAR struct circ_buf_s *circ,
|
||||
FAR void *dst, size_t bytes);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: circ_buf_skip
|
||||
*
|
||||
* Description:
|
||||
* Skip data form the circular buffer.
|
||||
*
|
||||
* Note:
|
||||
* That with only one concurrent reader and one concurrent writer,
|
||||
* you don't need extra locking to use these api.
|
||||
*
|
||||
* Input Parameters:
|
||||
* circ - Address of the circular buffer to be used.
|
||||
* bytes - Number of bytes to skip.
|
||||
*
|
||||
* Returned Value:
|
||||
* The bytes of get data is returned if the skip data is successful;
|
||||
* A negated errno value is returned on any failure.
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t circ_buf_skip(FAR struct circ_buf_s *circ, size_t bytes);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: circ_buf_write
|
||||
*
|
||||
* Description:
|
||||
* Write data to the circular buffer.
|
||||
*
|
||||
* Note:
|
||||
* That with only one concurrent reader and one concurrent writer,
|
||||
* you don't need extra locking to use these api.
|
||||
*
|
||||
* Input Parameters:
|
||||
* circ - Address of the circular buffer to be used.
|
||||
* src - The data to be added.
|
||||
* bytes - Number of bytes to be added.
|
||||
*
|
||||
* Returned Value:
|
||||
* The bytes of get data is returned if the write data is successful;
|
||||
* A negated errno value is returned on any failure.
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t circ_buf_write(FAR struct circ_buf_s *circ,
|
||||
FAR const void *src, size_t bytes);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: circ_buf_overwrite
|
||||
*
|
||||
* Description:
|
||||
* Write data to the circular buffer. It can overwrite old data when
|
||||
* circular buffer don't have enough space to store data.
|
||||
*
|
||||
* Note:
|
||||
* Usage circ_buf_overwrite () is dangerous. It should be only called
|
||||
* when the buffer is exclusived locked or when it is secured that no
|
||||
* other thread is accessing the buffer.
|
||||
*
|
||||
* Input Parameters:
|
||||
* circ - Address of the circular buffer to be used.
|
||||
* src - The data to be added.
|
||||
* bytes - Number of bytes to be added.
|
||||
*
|
||||
* Returned Value:
|
||||
* The bytes length of overwrite is returned if it's successful;
|
||||
* A negated errno value is returned on any failure.
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t circ_buf_overwrite(FAR struct circ_buf_s *circ,
|
||||
FAR const void *src, size_t bytes);
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -155,4 +155,10 @@ config MM_FILL_ALLOCATIONS
|
||||
Fill all malloc() allocations with 0xAA. This helps
|
||||
detecting uninitialized variable errors.
|
||||
|
||||
config MM_CIRC_BUF
|
||||
bool "Circular buffer support"
|
||||
default n
|
||||
---help---
|
||||
Build in support for the circular buffer management.
|
||||
|
||||
source "mm/iob/Kconfig"
|
||||
|
||||
@@ -43,6 +43,7 @@ include kmm_heap/Make.defs
|
||||
include mm_gran/Make.defs
|
||||
include shm/Make.defs
|
||||
include iob/Make.defs
|
||||
include circ_buf/Make.defs
|
||||
|
||||
BINDIR ?= bin
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
############################################################################
|
||||
# mm/circ_buf/Make.defs
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership. The
|
||||
# ASF licenses this file to you 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.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
# Circular buffer management
|
||||
|
||||
ifeq ($(CONFIG_MM_CIRC_BUF),y)
|
||||
CSRCS += circ_buf.c
|
||||
|
||||
# Add the circular buffer directory to the build
|
||||
|
||||
DEPPATH += --dep-path circ_buf
|
||||
VPATH += :circ_buf
|
||||
endif
|
||||
@@ -0,0 +1,496 @@
|
||||
/****************************************************************************
|
||||
* mm/circ_buf/circ_buf.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* Note about locking: There is no locking required while only one reader
|
||||
* and one writer is using the circular buffer.
|
||||
* For multiple writer and one reader there is only a need to lock the
|
||||
* writer. And vice versa for only one writer and multiple reader there is
|
||||
* only a need to lock the reader.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/mm/circ_buf.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: circ_buf_init
|
||||
*
|
||||
* Description:
|
||||
* Initialize a circular buffer.
|
||||
*
|
||||
* Input Parameters:
|
||||
* circ - Address of the circular buffer to be used.
|
||||
* base - A pointer to circular buffer's internal buffer. It can be
|
||||
* provided by caller because sometimes the creation of buffer
|
||||
* is special or needs to preallocated, eg: DMA buffer.
|
||||
* If NULL, a buffer of the given size will be allocated.
|
||||
* bytes - The size of the internal buffer.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; A negated errno value is returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int circ_buf_init(FAR struct circ_buf_s *circ, FAR void *base, size_t bytes)
|
||||
{
|
||||
if (!circ || (base && !bytes))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
circ->external = !!base;
|
||||
|
||||
if (!base && bytes)
|
||||
{
|
||||
base = kmm_malloc(bytes);
|
||||
if (!base)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
circ->base = base;
|
||||
circ->size = bytes;
|
||||
circ->head = 0;
|
||||
circ->tail = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: circ_buf_resize
|
||||
*
|
||||
* Description:
|
||||
* Resize a circular buffer (change buffer size).
|
||||
*
|
||||
* Input Parameters:
|
||||
* circ - Address of the circular buffer to be used.
|
||||
* bytes - The size of the internal buffer.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; A negated errno value is returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int circ_buf_resize(FAR struct circ_buf_s *circ, size_t bytes)
|
||||
{
|
||||
FAR void *tmp;
|
||||
size_t len;
|
||||
|
||||
if (!circ || circ->external)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tmp = kmm_malloc(bytes);
|
||||
if (!tmp)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
len = circ_buf_used(circ);
|
||||
if (bytes < len)
|
||||
{
|
||||
circ_buf_skip(circ, len - bytes);
|
||||
len = bytes;
|
||||
}
|
||||
|
||||
circ_buf_read(circ, tmp, len);
|
||||
|
||||
kmm_free(circ->base);
|
||||
|
||||
circ->base = tmp;
|
||||
circ->size = bytes;
|
||||
circ->head = len;
|
||||
circ->tail = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: circ_buf_reset
|
||||
*
|
||||
* Description:
|
||||
* Remove the entire circular buffer content.
|
||||
*
|
||||
* Input Parameters:
|
||||
* circ - Address of the circular buffer to be used.
|
||||
****************************************************************************/
|
||||
|
||||
void circ_buf_reset(FAR struct circ_buf_s *circ)
|
||||
{
|
||||
if (circ)
|
||||
{
|
||||
circ->head = circ->tail = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: circ_buf_uninit
|
||||
*
|
||||
* Description:
|
||||
* Free the circular buffer.
|
||||
*
|
||||
* Input Parameters:
|
||||
* circ - Address of the circular buffer to be used.
|
||||
****************************************************************************/
|
||||
|
||||
void circ_buf_uninit(FAR struct circ_buf_s *circ)
|
||||
{
|
||||
if (circ && !circ->external)
|
||||
{
|
||||
kmm_free(circ->base);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: circ_buf_size
|
||||
*
|
||||
* Description:
|
||||
* Return size of the circular buffer.
|
||||
*
|
||||
* Input Parameters:
|
||||
* circ - Address of the circular buffer to be used.
|
||||
****************************************************************************/
|
||||
|
||||
size_t circ_buf_size(FAR struct circ_buf_s *circ)
|
||||
{
|
||||
if (circ)
|
||||
{
|
||||
return circ->size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: circ_buf_used
|
||||
*
|
||||
* Description:
|
||||
* Return the used bytes of the circular buffer.
|
||||
*
|
||||
* Input Parameters:
|
||||
* circ - Address of the circular buffer to be used.
|
||||
****************************************************************************/
|
||||
|
||||
size_t circ_buf_used(FAR struct circ_buf_s *circ)
|
||||
{
|
||||
if (circ)
|
||||
{
|
||||
return circ->head - circ->tail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: circ_buf_space
|
||||
*
|
||||
* Description:
|
||||
* Return the remaing space of the circular buffer.
|
||||
*
|
||||
* Input Parameters:
|
||||
* circ - Address of the circular buffer to be used.
|
||||
****************************************************************************/
|
||||
|
||||
size_t circ_buf_space(FAR struct circ_buf_s *circ)
|
||||
{
|
||||
return circ_buf_size(circ) - circ_buf_used(circ);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: circ_buf_is_empty
|
||||
*
|
||||
* Description:
|
||||
* Return true if the circular buffer is empty.
|
||||
*
|
||||
* Input Parameters:
|
||||
* circ - Address of the circular buffer to be used.
|
||||
****************************************************************************/
|
||||
|
||||
bool circ_buf_is_empty(FAR struct circ_buf_s *circ)
|
||||
{
|
||||
return !circ_buf_used(circ);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: circ_buf_is_full
|
||||
*
|
||||
* Description:
|
||||
* Return true if the circular buffer is full.
|
||||
*
|
||||
* Input Parameters:
|
||||
* circ - Address of the circular buffer to be used.
|
||||
****************************************************************************/
|
||||
|
||||
bool circ_buf_is_full(FAR struct circ_buf_s *circ)
|
||||
{
|
||||
return !circ_buf_space(circ);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: circ_buf_peek
|
||||
*
|
||||
* Description:
|
||||
* Get data form the circular buffer without removing
|
||||
*
|
||||
* Note :
|
||||
* That with only one concurrent reader and one concurrent writer,
|
||||
* you don't need extra locking to use these api.
|
||||
*
|
||||
* Input Parameters:
|
||||
* circ - Address of the circular buffer to be used.
|
||||
* dst - Address where to store the data.
|
||||
* bytes - Number of bytes to get.
|
||||
*
|
||||
* Returned Value:
|
||||
* The bytes of get data is returned if the peek data is successful;
|
||||
* A negated errno value is returned on any failure.
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t circ_buf_peek(FAR struct circ_buf_s *circ,
|
||||
FAR void *dst, size_t bytes)
|
||||
{
|
||||
size_t len;
|
||||
size_t off;
|
||||
|
||||
if (!circ)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
len = circ_buf_used(circ);
|
||||
off = circ->tail % circ->size;
|
||||
|
||||
if (bytes > len)
|
||||
{
|
||||
bytes = len;
|
||||
}
|
||||
|
||||
len = circ->size - off;
|
||||
if (bytes < len)
|
||||
{
|
||||
len = bytes;
|
||||
}
|
||||
|
||||
memcpy(dst, circ->base + off, len);
|
||||
memcpy(dst + len, circ->base, bytes - len);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: circ_buf_read
|
||||
*
|
||||
* Description:
|
||||
* Get data form the circular buffer.
|
||||
*
|
||||
* Note :
|
||||
* That with only one concurrent reader and one concurrent writer,
|
||||
* you don't need extra locking to use these api.
|
||||
*
|
||||
* Input Parameters:
|
||||
* circ - Address of the circular buffer to be used.
|
||||
* dst - Address where to store the data.
|
||||
* bytes - Number of bytes to get.
|
||||
*
|
||||
* Returned Value:
|
||||
* The bytes of get data is returned if the read data is successful;
|
||||
* A negated errno value is returned on any failure.
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t circ_buf_read(FAR struct circ_buf_s *circ,
|
||||
FAR void *dst, size_t bytes)
|
||||
{
|
||||
if (!circ || !dst)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bytes = circ_buf_peek(circ, dst, bytes);
|
||||
circ->tail += bytes;
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: circ_buf_skip
|
||||
*
|
||||
* Description:
|
||||
* Skip data form the circular buffer.
|
||||
*
|
||||
* Note :
|
||||
* That with only one concurrent reader and one concurrent writer,
|
||||
* you don't need extra locking to use these api.
|
||||
*
|
||||
* Input Parameters:
|
||||
* circ - Address of the circular buffer to be used.
|
||||
* bytes - Number of bytes to skip.
|
||||
*
|
||||
* Returned Value:
|
||||
* The bytes of get data is returned if the skip data is successful;
|
||||
* A negated errno value is returned on any failure.
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t circ_buf_skip(FAR struct circ_buf_s *circ, size_t bytes)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
if (!circ)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
len = circ_buf_used(circ);
|
||||
|
||||
if (bytes > len)
|
||||
{
|
||||
bytes = len;
|
||||
}
|
||||
|
||||
circ->tail += bytes;
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: circ_buf_write
|
||||
*
|
||||
* Description:
|
||||
* Write data to the circular buffer.
|
||||
*
|
||||
* Note :
|
||||
* That with only one concurrent reader and one concurrent writer,
|
||||
* you don't need extra locking to use these api.
|
||||
*
|
||||
* Input Parameters:
|
||||
* circ - Address of the circular buffer to be used.
|
||||
* src - The data to be added.
|
||||
* bytes - Number of bytes to be added.
|
||||
*
|
||||
* Returned Value:
|
||||
* The bytes of get data is returned if the write data is successful;
|
||||
* A negated errno value is returned on any failure.
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t circ_buf_write(FAR struct circ_buf_s *circ,
|
||||
FAR const void *src, size_t bytes)
|
||||
{
|
||||
size_t space;
|
||||
size_t off;
|
||||
|
||||
if (!circ || !src)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
space = circ_buf_space(circ);
|
||||
off = circ->head % circ->size;
|
||||
if (bytes > space)
|
||||
{
|
||||
bytes = space;
|
||||
}
|
||||
|
||||
space = circ->size - off;
|
||||
if (bytes < space)
|
||||
{
|
||||
space = bytes;
|
||||
}
|
||||
|
||||
memcpy(circ->base + off, src, space);
|
||||
memcpy(circ->base, src + space, bytes - space);
|
||||
circ->head += bytes;
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: circ_buf_overwrite
|
||||
*
|
||||
* Description:
|
||||
* Write data to the circular buffer. It can overwrite old data when
|
||||
* circular buffer don't have enough space to store data.
|
||||
*
|
||||
* Note:
|
||||
* Usage circ_buf_overwrite () is dangerous. It should be only called
|
||||
* when the buffer is exclusived locked or when it is secured that no
|
||||
* other thread is accessing the buffer.
|
||||
*
|
||||
* Input Parameters:
|
||||
* circ - Address of the circular buffer to be used.
|
||||
* src - The data to be added.
|
||||
* bytes - Number of bytes to be added.
|
||||
*
|
||||
* Returned Value:
|
||||
* The bytes length of overwrite is returned if it's successful;
|
||||
* A negated errno value is returned on any failure.
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t circ_buf_overwrite(FAR struct circ_buf_s *circ,
|
||||
FAR const void *src, size_t bytes)
|
||||
{
|
||||
size_t overwrite = 0;
|
||||
size_t space;
|
||||
size_t off;
|
||||
|
||||
if (!circ || !src)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (bytes > circ->size)
|
||||
{
|
||||
src += bytes - circ->size;
|
||||
bytes = circ->size;
|
||||
}
|
||||
|
||||
space = circ_buf_space(circ);
|
||||
if (bytes > space)
|
||||
{
|
||||
overwrite = bytes - space;
|
||||
}
|
||||
|
||||
off = circ->head % circ->size;
|
||||
space = circ->size - off;
|
||||
if (bytes < space)
|
||||
{
|
||||
space = bytes;
|
||||
}
|
||||
|
||||
memcpy(circ->base + off, src, space);
|
||||
memcpy(circ->base, src + space, bytes - space);
|
||||
circ->head += bytes;
|
||||
circ->tail += overwrite;
|
||||
|
||||
return overwrite;
|
||||
}
|
||||
Reference in New Issue
Block a user