/****************************************************************************** * file lib/management/fifo.c * author YuLiang * version 1.0.0 * date 21-Feb-2023 * brief This file provides all the fifo operation functions. * ****************************************************************************** * Attention * *

© COPYRIGHT(c) 2021 LandPower

* * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of LandPower nor the names of its contributors may be used to * endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ******************************************************************************/ /* Includes ------------------------------------------------------------------*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* 标准C库头文件. */ /* 用户代码头文件. */ #include "cmd.h" #include "fifo.h" /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private typedef -----------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ static array_t *fifo = NULL; /* Private function prototypes -----------------------------------------------*/ /* Internal functions --------------------------------------------------------*/ /* 显示 fifo 的使用情况. */ CMD(show_fifo, show_fifo_cmd, "show fifo", "Show\n" "Fifo\n") { uint32_t id = 0; fifo_t *fifo_node = NULL; for (id = 0; id < array_active(fifo); id++) { fifo_node = array_lookup(fifo, id); if (NULL == fifo_node) { continue; } fifo_show(id); } return CMD_SUCCESS; } /* Interface functions -------------------------------------------------------*/ /* 初始化 fifo 全局结构 */ int32_t fifo_init(void) { #if 0 fifo = array_init(16, MTYPE_FIFO); if (!fifo) { log_err(LOG_FIFO, "ERROR at array init!"); return E_MEM; } #endif cmd_install_element(COMMON_NODE, &show_fifo_cmd); return E_NONE; } /* 创建 1 个 fifo. */ int32_t fifo_create(char* name, uint32_t size) { fifo_t *fifo_node = NULL; /* 初始化. */ fifo_node = XMALLOC(MTYPE_FIFO, sizeof(fifo_t)); if (!fifo_node) { return E_MEM; } snprintf(fifo_node->name, FIFO_NAME_LEN, "%s", name); fifo_node->size = size; /* 申请互斥锁, 用于通知读线程读取有效. */ if (sem_init(&fifo_node->sem, 0, 0) != 0) { XFREE(MTYPE_FIFO, fifo_node); DBG(DBG_M_FIFO_ERR, "%s ERROR at sem init return %s!\r\n", name, safe_strerror(errno)); return E_SYS_CALL; } /* 申请信号量, 防止多个线程同时操作 fifo. */ if (pthread_mutex_init(&fifo_node->mutex, NULL) != 0) { XFREE(MTYPE_FIFO, fifo_node); sem_destroy(&fifo_node->sem); DBG(DBG_M_FIFO_ERR, "%s ERROR at sem init return %s!\r\n", name, safe_strerror(errno)); return E_SYS_CALL; } /* 申请 fifo 空间. */ fifo_node->data = XMALLOC(MTYPE_FIFO, sizeof(void *) * size); if (!fifo_node->data) { XFREE(MTYPE_FIFO, fifo_node); sem_destroy(&fifo_node->sem); pthread_mutex_destroy(&fifo_node->mutex); return E_MEM; } /* 添加到全局结构体. */ return array_append(fifo, fifo_node, MTYPE_FIFO); } /* 往 fifo 中写入一条数据. */ int32_t fifo_write(uint32_t id, void *data, int32_t len) { int32_t index = 0; fifo_t *fifo_node = array_get(fifo, id); void *temp = NULL; /* 参数检查. */ if (!fifo_node) { DBG_Q(DBG_M_FIFO_ERR, "#7\r\n"); return E_NOT_FOUND; } /* 申请数据空间. */ temp = XMALLOC_Q(MTYPE_FIFO, len); if (!temp) { return E_MEM; } memcpy(temp, data, len); pthread_mutex_lock(&fifo_node->mutex); /* 判断 fifo 是否满了. */ index = fifo_node->cur + 1; if (index == fifo_node->size) { index = 0; } if (index == fifo_node->valid) { DBG_Q(DBG_M_FIFO_ERR, "#8 %d\r\n", id); XFREE(MTYPE_FIFO, temp); pthread_mutex_unlock(&fifo_node->mutex); return E_MEM; } /* 数据加入 fifo. */ fifo_node->data[fifo_node->cur] = temp; fifo_node->used++; if (fifo_node->used > fifo_node->max) { fifo_node->max = fifo_node->used; } fifo_node->cur = index; sem_post(&fifo_node->sem); pthread_mutex_unlock(&fifo_node->mutex); return len; } /* 从 fifo 中读取数据, 注意, 只能一个进程进行读取. */ int32_t fifo_read(uint32_t id, void **data) { fifo_t *fifo_node = array_get(fifo, id); /* 参数检查. */ if (!fifo_node) { DBG(DBG_M_FIFO_ERR, "Fifo %d is not found!\r\n", id); return E_NOT_FOUND; } /* 等待有效数据, 如果有效, 返回数据. */ while (fifo_node->valid == fifo_node->cur) { sem_wait(&fifo_node->sem); } *data = fifo_node->data[fifo_node->valid]; return E_NONE; } /* 释放 fifo 数据, 因为节省了一次内存申请, 所以必须手动释放 fifo 数据. */ int32_t fifo_push(uint32_t id) { uint32_t index = 0; fifo_t *fifo_node = array_get(fifo, id); /* 检查参数. */ if (!fifo_node) { DBG(DBG_M_FIFO_ERR, "Fifo %d is not found!\r\n", id); return E_NOT_FOUND; } /* 释放数据. */ if (fifo_node->valid != fifo_node->cur) { pthread_mutex_lock(&fifo_node->mutex); XFREE(MTYPE_FIFO, fifo_node->data[fifo_node->valid]); fifo_node->data[fifo_node->valid] = NULL; index = fifo_node->valid + 1; if (index == fifo_node->size) { index = 0; } fifo_node->used--; fifo_node->valid = index; pthread_mutex_unlock(&fifo_node->mutex); } return E_NONE; } /* 显示 fifo 的使用情况. */ void fifo_show(uint32_t id) { fifo_t *fifo_node = NULL; fifo_node = array_lookup(fifo, id); if (NULL == fifo_node) { return; } printh("%-32s %-2d %-2d %-2d %-2d %-2d %-2d\r\n", fifo_node->name, id, fifo_node->size, fifo_node->cur, fifo_node->valid, fifo_node->used, fifo_node->max); } /************************ (C) COPYRIGHT LandPower ***** END OF FILE ****************/