You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
	
	
		
			274 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			C
		
	
		
		
			
		
	
	
			274 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			C
		
	
|   
											2 months ago
										 | /******************************************************************************
 | ||
|  |  * 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 | ||
|  |  * | ||
|  |  * <h2><center>© COPYRIGHT(c) 2021 LandPower</center></h2> | ||
|  |  * | ||
|  |  * 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) | ||
|  | { | ||
|  |     fifo = array_init(16, MTYPE_FIFO); | ||
|  |     if (!fifo) | ||
|  |     { | ||
|  |         log_err(LOG_FIFO, "ERROR at array init!"); | ||
|  |         return E_MEM; | ||
|  |     } | ||
|  | 
 | ||
|  |     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 ****************/ |