首页 > 编程语言 >UcOs-III 源码阅读: os_mem.c

UcOs-III 源码阅读: os_mem.c

时间:2024-10-31 17:58:00浏览次数:4  
标签:err UcOs ERR mem MEM 源码 内存 OS

//作用:固定大小内存管理器的代码,内存分区代码

/*
*********************************************************************************************************
*                                              uC/OS-III
*                                        The Real-Time Kernel
*
*                    Copyright 2009-2022 Silicon Laboratories Inc. www.silabs.com
*
*                                 SPDX-License-Identifier: APACHE-2.0
*
*               This software is subject to an open source license and is distributed by
*                Silicon Laboratories Inc. pursuant to the terms of the Apache License,
*                    Version 2.0 available at www.apache.org/licenses/LICENSE-2.0.
*
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                      内存分区管理
*
* 文件: os_mem.c
* 版本: V3.08.02
*********************************************************************************************************
*/

#define   MICRIUM_SOURCE
#include "os.h"

#ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
const  CPU_CHAR  *os_mem__c = "$Id: $";
#endif


#if (OS_CFG_MEM_EN > 0u)
/*
************************************************************************************************************************
*                                               创建内存分区
*
* 描述: 创建一个由 uC/OS-III 管理的固定大小的内存分区。
*
* 参数: p_mem    是指向用户内存空间中分配的内存分区控制块的指针。
*
*               p_name   是指向 ASCII 字符串的指针,用于为内存分区提供名称。
*
*               p_addr   是内存分区的起始地址。
*
*               n_blks   是从分区中创建的内存块数量。
*
*               blk_size 是内存分区中每个块的大小(以字节为单位)。
*
*               p_err    是指向包含错误消息的变量的指针,此函数会将其设置为以下之一:
*
*                            OS_ERR_NONE                    如果内存分区已正确创建
*                            OS_ERR_ILLEGAL_CREATE_RUN_TIME 如果在调用 OSSafetyCriticalStart() 之后尝试创建内存分区
*                            OS_ERR_MEM_CREATE_ISR          如果从 ISR 中调用此函数
*                            OS_ERR_MEM_INVALID_BLKS        用户指定的块数无效(必须 >= 2)
*                            OS_ERR_MEM_INVALID_P_ADDR      如果指定的内存分区存储地址无效,或者块未对齐到指针边界
*                            OS_ERR_MEM_INVALID_SIZE        用户指定的块大小无效
*                                                             - 必须大于指针的大小
*                                                             - 必须能够容纳整数个指针
*                            OS_ERR_OBJ_CREATED             如果内存分区已创建
* 返回: 无
*
* 注意: 无
************************************************************************************************************************
*/

void OSMemCreate(OS_MEM *p_mem, CPU_CHAR *p_name, void *p_addr, OS_MEM_QTY n_blks, OS_MEM_SIZE blk_size, OS_ERR *p_err)
{
#if (OS_CFG_ARG_CHK_EN > 0u)
    CPU_DATA align_msk;
#endif
    OS_MEM_QTY i;
    OS_MEM_QTY loops;
    CPU_INT08U *p_blk;
    void **p_link;
    CPU_SR_ALLOC();

#ifdef OS_SAFETY_CRITICAL
    if (p_err == (OS_ERR *)0) {
        OS_SAFETY_CRITICAL_EXCEPTION();
        return;
    }
#endif

#ifdef OS_SAFETY_CRITICAL_IEC61508
    if (OSSafetyCriticalStartFlag == OS_TRUE) {
        *p_err = OS_ERR_ILLEGAL_CREATE_RUN_TIME;
        return;
    }
#endif

#if (OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u)
    if (OSIntNestingCtr > 0u) {  /* 不允许从 ISR 调用 */
        *p_err = OS_ERR_MEM_CREATE_ISR;
        return;
    }
#endif

#if (OS_CFG_ARG_CHK_EN > 0u)
    if (p_addr == (void *)0) {  /* 必须传递有效的内存分区地址 */
        *p_err = OS_ERR_MEM_INVALID_P_ADDR;
        return;
    }
    if (n_blks < 2u) {  /* 每个分区至少需要 2 个块 */
        *p_err = OS_ERR_MEM_INVALID_BLKS;
        return;
    }
    if (blk_size < sizeof(void *)) {  /* 必须包含至少一个指针的空间 */
        *p_err = OS_ERR_MEM_INVALID_SIZE;
        return;
    }
    align_msk = sizeof(void *) - 1u;
    if (align_msk > 0u) {
        if (((CPU_ADDR)p_addr & align_msk) != 0u) {  /* 必须对齐到指针大小 */
            *p_err = OS_ERR_MEM_INVALID_P_ADDR;
            return;
        }
        if ((blk_size & align_msk) != 0u) {  /* 块大小必须是地址大小的倍数 */
            *p_err = OS_ERR_MEM_INVALID_SIZE;
            return;
        }
    }
#endif

    p_link = (void **)p_addr;  /* 创建空闲内存块的链表 */
    p_blk = (CPU_INT08U *)p_addr;
    loops = n_blks - 1u;
    for (i = 0u; i < loops; i++) {
        p_blk += blk_size;
        *p_link = (void *)p_blk;  /* 在当前块中保存指向下一个块的指针 */
        p_link = (void **)(void *)p_blk;  /* 定位到下一个块 */
    }
    *p_link = (void *)0;  /* 最后一个内存块指向 NULL */

    CPU_CRITICAL_ENTER();
#if (OS_OBJ_TYPE_REQ > 0u)
#if (OS_CFG_OBJ_CREATED_CHK_EN > 0u)
    if (p_mem->Type == OS_OBJ_TYPE_MEM) {
        CPU_CRITICAL_EXIT();
        *p_err = OS_ERR_OBJ_CREATED;
        return;
    }
#endif
    p_mem->Type = OS_OBJ_TYPE_MEM;  /* 设置对象类型 */
#endif
#if (OS_CFG_DBG_EN > 0u)
    p_mem->NamePtr = p_name;  /* 保存内存分区的名称 */
#else
    (void)p_name;
#endif
    p_mem->AddrPtr = p_addr;  /* 存储内存分区的起始地址 */
    p_mem->FreeListPtr = p_addr;  /* 初始化指向空闲块池的指针 */
    p_mem->NbrFree = n_blks;  /* 存储 MCB 中的空闲块数量 */
    p_mem->NbrMax = n_blks;
    p_mem->BlkSize = blk_size;  /* 存储每个内存块的大小 */

#if (OS_CFG_DBG_EN > 0u)
    OS_MemDbgListAdd(p_mem);
    OSMemQty++;
#endif

    OS_TRACE_MEM_CREATE(p_mem, p_name);
    CPU_CRITICAL_EXIT();
    *p_err = OS_ERR_NONE;
}


/*
************************************************************************************************************************
*                                                  获取内存块
*
* 描述: 从内存分区中获取一个内存块。
*
* 参数: p_mem   是指向内存分区控制块的指针
*
*               p_err   是指向包含错误消息的变量的指针,此函数会将其设置为以下之一:
*
*                           OS_ERR_NONE               如果内存分区已正确创建
*                           OS_ERR_MEM_INVALID_P_MEM  如果传递了 NULL 指针作为 'p_mem'
*                           OS_ERR_MEM_NO_FREE_BLKS   如果没有更多的空闲内存块可以分配给调用者
*                           OS_ERR_OBJ_TYPE           如果 'p_mem' 指向的不是一个内存分区
*
* 返回: 如果没有检测到错误,返回指向内存块的指针
*              如果检测到错误,返回指向 NULL 的指针
*
* 注意: 无
************************************************************************************************************************
*/

void *OSMemGet(OS_MEM *p_mem, OS_ERR *p_err)
{
    void *p_blk;
    CPU_SR_ALLOC();

#ifdef OS_SAFETY_CRITICAL
    if (p_err == (OS_ERR *)0) {
        OS_SAFETY_CRITICAL_EXCEPTION();
        return ((void *)0);
    }
#endif

    OS_TRACE_MEM_GET_ENTER(p_mem);

#if (OS_CFG_ARG_CHK_EN > 0u)
    if (p_mem == (OS_MEM *)0) {  /* 必须指向一个有效的内存分区 */
        OS_TRACE_MEM_GET_FAILED(p_mem);
        OS_TRACE_MEM_GET_EXIT(OS_ERR_MEM_INVALID_P_MEM);
        *p_err = OS_ERR_MEM_INVALID_P_MEM;
        return ((void *)0);
    }
#endif

#if (OS_CFG_OBJ_TYPE_CHK_EN > 0u)
    if (p_mem->Type != OS_OBJ_TYPE_MEM) {  /* 确保内存块已创建 */
        OS_TRACE_MEM_GET_EXIT(OS_ERR_OBJ_TYPE);
        *p_err = OS_ERR_OBJ_TYPE;
        return ((void *)0);
    }
#endif

    CPU_CRITICAL_ENTER();
    if (p_mem->NbrFree == 0u) {  /* 检查是否有空闲的内存块 */
        CPU_CRITICAL_EXIT();
        OS_TRACE_MEM_GET_FAILED(p_mem);
        OS_TRACE_MEM_GET_EXIT(OS_ERR_MEM_NO_FREE_BLKS);
        *p_err = OS_ERR_MEM_NO_FREE_BLKS;  /* 通知调用者内存分区为空 */
        return ((void *)0);  /* 返回 NULL 指针给调用者 */
    }
    p_blk = p_mem->FreeListPtr;  /* 指向下一个空闲的内存块 */
    p_mem->FreeListPtr = *(void **)p_blk;  /* 调整指针到新的空闲列表 */
    p_mem->NbrFree--;  /* 该分区中的内存块数量减少一个 */
    CPU_CRITICAL_EXIT();
    OS_TRACE_MEM_GET(p_mem);
    OS_TRACE_MEM_GET_EXIT(OS_ERR_NONE);
    *p_err = OS_ERR_NONE;  /* 没有错误 */
    return (p_blk);  /* 返回内存块给调用者 */
}


/*
************************************************************************************************************************
*                                                 释放内存块
*
* 描述: 将一个内存块返回到内存分区。
*
* 参数: p_mem    是指向内存分区控制块的指针
*
*               p_blk    是指向要释放的内存块的指针
*
*               p_err    是指向包含此函数返回的错误代码的变量的指针。
*
*                            OS_ERR_NONE               如果内存块已插入到分区中
*                            OS_ERR_MEM_FULL           如果将内存块返回到一个已经满的内存分区(释放的块比分配的多!)
*                            OS_ERR_MEM_INVALID_P_BLK  如果传递了 NULL 指针作为要释放的块
*                            OS_ERR_MEM_INVALID_P_MEM  如果传递了 NULL 指针作为 'p_mem'
*                            OS_ERR_OBJ_TYPE           如果 'p_mem' 指向的不是一个内存分区
*
* 返回: 无
*
* 注意: 无
************************************************************************************************************************
*/

void OSMemPut(OS_MEM *p_mem, void *p_blk, OS_ERR *p_err)
{
    CPU_SR_ALLOC();

#ifdef OS_SAFETY_CRITICAL
    if (p_err == (OS_ERR *)0) {
        OS_SAFETY_CRITICAL_EXCEPTION();
        return;
    }
#endif

    OS_TRACE_MEM_PUT_ENTER(p_mem, p_blk);

#if (OS_CFG_ARG_CHK_EN > 0u)
    if (p_mem == (OS_MEM *)0) {  /* 必须指向一个有效的内存分区 */
        OS_TRACE_MEM_PUT_FAILED(p_mem);
        OS_TRACE_MEM_PUT_EXIT(OS_ERR_MEM_INVALID_P_MEM);
        *p_err = OS_ERR_MEM_INVALID_P_MEM;
        return;
    }
    if (p_blk == (void *)0) {  /* 必须释放一个有效的块 */
        OS_TRACE_MEM_PUT_FAILED(p_mem);
        OS_TRACE_MEM_PUT_EXIT(OS_ERR_MEM_INVALID_P_BLK);
        *p_err = OS_ERR_MEM_INVALID_P_BLK;
        return;
    }
#endif

#if (OS_CFG_OBJ_TYPE_CHK_EN > 0u)
    if (p_mem->Type != OS_OBJ_TYPE_MEM) {  /* 确保内存块已创建 */
        OS_TRACE_MEM_PUT_EXIT(OS_ERR_OBJ_TYPE);
        *p_err = OS_ERR_OBJ_TYPE;
        return;
    }
#endif

    CPU_CRITICAL_ENTER();
    if (p_mem->NbrFree >= p_mem->NbrMax) {  /* 确保所有块未全部返回 */
        CPU_CRITICAL_EXIT();
        OS_TRACE_MEM_PUT_FAILED(p_mem);
        OS_TRACE_MEM_PUT_EXIT(OS_ERR_MEM_FULL);
        *p_err = OS_ERR_MEM_FULL;
        return;
    }
    *(void **)p_blk = p_mem->FreeListPtr;  /* 将释放的块插入到空闲块列表中 */
    p_mem->FreeListPtr = p_blk;
    p_mem->NbrFree++;  /* 该分区中的内存块数量增加一个 */
    CPU_CRITICAL_EXIT();
    OS_TRACE_MEM_PUT(p_mem);
    OS_TRACE_MEM_PUT_EXIT(OS_ERR_NONE);
    *p_err = OS_ERR_NONE;  /* 通知调用者内存块已释放 */
}


/*
************************************************************************************************************************
*                                           将内存分区添加到调试列表
*
* 描述: 此函数由 OSMemCreate() 调用,将内存分区添加到调试表中。
*
* 参数: p_mem    是指向内存分区的指针
*
* 返回: 无
*
* 注意: 此函数是 uC/OS-III 的内部函数,您的应用程序不应调用它。
************************************************************************************************************************
*/

#if (OS_CFG_DBG_EN > 0u)
void  OS_MemDbgListAdd (OS_MEM  *p_mem)
{
    p_mem->DbgPrevPtr               = (OS_MEM *)0;
    if (OSMemDbgListPtr == (OS_MEM *)0) {
        p_mem->DbgNextPtr           = (OS_MEM *)0;
    } else {
        p_mem->DbgNextPtr           =  OSMemDbgListPtr;
        OSMemDbgListPtr->DbgPrevPtr =  p_mem;
    }
    OSMemDbgListPtr                 =  p_mem;
}
#endif


/*
************************************************************************************************************************
*                                           初始化内存分区管理器
*
* 描述: 此函数由 uC/OS-III 调用,用于初始化内存分区管理器。您的应用程序必须不调用此函数。
*
* 参数: 无
*
* 返回: 无
*
* 注意: 此函数是 uC/OS-III 的内部函数,您的应用程序不应调用它。
************************************************************************************************************************
*/

void  OS_MemInit (OS_ERR  *p_err)
{
#if (OS_CFG_DBG_EN > 0u)
    OSMemDbgListPtr = (OS_MEM *)0;
    OSMemQty        = 0u;
#endif
   *p_err           = OS_ERR_NONE;
}
#endif

标签:err,UcOs,ERR,mem,MEM,源码,内存,OS
From: https://www.cnblogs.com/lanlincmos/p/18518570

相关文章

  • Python——石头剪刀布(附源码+多模式二改优化版)
    编程初学者通常会从简单的项目开始,以建立基础并增强信心。石头剪刀布游戏是一个很好的起点,因为它涉及到基本的逻辑判断、用户输入处理和随机数生成。本文将详细介绍如何使用Python编写一个石头剪刀布游戏,并提供完整的代码和解释。目录一、游戏介绍二、基本代码解析与实现......
  • Ubuntu24安装Gitlab源码管理系统
    Ubuntu20.04LTS,22.04LTS,24.04LTS安装和配置所需的依赖sudoapt-getupdatesudoapt-getinstall-ycurlopenssh-serverca-certificatestzdataperl(可选)如果要使用Postfix来发送电子邮件通知,执行以下安装命令。sudoapt-getinstall-ypostfix如果您想使用......
  • UcOs-III 源码阅读: os_mutex.c
    //作用:管理互斥量的代码/***********************************************************************************************************uC/OS-III*TheReal-TimeKernel**......
  • 斐波那契时间序列,精准捕捉市场拐点 MT4免费公式源码!
    指标名称:斐波那契时间序列版本:MT4ver.2.01斐波那契时间序列是一种技术分析工具,通过将斐波那契数列(如1,2,3,5,8,13等)应用于时间轴上,用于预测市场价格的时间周期拐点。斐波那契时间序列在股票、外汇和其他市场分析中常用,帮助预测趋势反转或调整发生的时间节点。斐波那......
  • java+vue计算机毕设冬季供热有限公司网站建设【开题+程序+论文+源码】
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着冬季气温的逐渐降低,供热服务成为了城市居民生活中不可或缺的一部分。冬季供热有限公司作为城市供热的主要提供者,承担着保障居民温暖过冬的重要职......
  • java+vue计算机毕设第二课堂学分认定系统【开题+程序+论文+源码】
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景在高等教育日益重视综合素质培养的今天,第二课堂作为第一课堂的有效补充,其在拓宽学生知识面、提升实践能力、增强综合素质等方面发挥着不可替代的作用......
  • 基于Springboot在线旅游景点网站【附源码+文档】
    ......
  • 深入解析 Memcached原理、架构与最佳实践
    1.引言什么是Memcached?Memcached是一个高性能的分布式内存对象缓存系统,旨在通过减少数据库负载来加速动态Web应用程序。它以键值对的形式将数据存储在内存中,允许应用程序快速读取数据,从而提高响应速度和系统的可扩展性。由于其简单的设计和高效的性能,Memcached被广......
  • 2024最新多客游戏陪玩,语音聊天系统源码,IM聊天服务使用说明,欢迎学习下载!
    多客陪玩系统-游戏陪玩系统,线下家政,游戏代练系统,开黑陪玩系统:陪玩系统源码,高质量的陪玩系统源码,游戏陪玩APP源码开发,语音陪玩源码搭建多客陪玩系统,游戏开黑陪玩,线下搭子,开黑陪玩系统 系统基于TP6+Uni-app框架开发;客户移动端采用uni-app开发,管理后台TH6开发。系统支持微信......