实现原理

cache API中的非缓存内存分配接口是通过内核堆或arch API接口实现的。

  • 如果CPU没有cache则cache API应该通过宏配置去掉,即使没有去掉实际也会变成内核堆接口的调用。
  • 如果系统没有DMA区,或arch层没有提供CACHEOP_pfuncDmaMalloc回调,则内存的分配与释放也是通过内核堆接口实现的,但cache同步接口是有效的,也是驱动层需要调用的。
  • 如果arch层提供了CACHEOP_pfuncDmaMalloc回调,则通过回调函数实现内存的分配与释放,此时cache同步接口实际为空,也无需驱动层调用。
  • 如果处理器的cache是一致性的,则从DATA区配内存,否则从DMA区分配内存。

arch层中CACHEOP_pfuncDmaMalloc回调函数的实现一般是API_VmmDmaAllocAlignWithFlags函数实现的,即使用DMA区内存进行分配与释放。

实现源码

内核实现源码

/*********************************************************************************************************
** 函数名称: API_CacheDmaMalloc
** 功能描述: 开辟一块非缓冲的内存
** 输 入  :
**           stBytes                       长度
** 输 出  : 开辟的空间首地址
*********************************************************************************************************/
PVOID    API_CacheDmaMalloc (size_t   stBytes)
{return  ((_G_cacheopLib.CACHEOP_pfuncDmaMalloc == LW_NULL) ?(__KHEAP_ALLOC_ALIGN(stBytes, LW_CFG_CPU_ARCH_CACHE_LINE)) :(_G_cacheopLib.CACHEOP_pfuncDmaMalloc(stBytes)));
}
/*********************************************************************************************************
** 函数名称: API_CacheDmaMallocAlign
** 功能描述: 开辟一块非缓冲的内存, 指定内存对齐关系
** 输 入  :
**           stBytes                       长度
**           stAlign                       对齐字节数
** 输 出  : 开辟的空间首地址
*********************************************************************************************************/
PVOID    API_CacheDmaMallocAlign (size_t   stBytes, size_t  stAlign)
{size_t  stAlignMax;//判定stAlign是否为2的幂次if (stAlign & (stAlign - 1)) {_ErrorHandle(EINVAL);return  (LW_NULL);}stAlignMax = (stAlign > LW_CFG_CPU_ARCH_CACHE_LINE) ? stAlign : LW_CFG_CPU_ARCH_CACHE_LINE;return  ((_G_cacheopLib.CACHEOP_pfuncDmaMallocAlign == LW_NULL) ?(__KHEAP_ALLOC_ALIGN(stBytes, stAlignMax)) :(_G_cacheopLib.CACHEOP_pfuncDmaMallocAlign(stBytes, stAlign)));
}
/*********************************************************************************************************
** 函数名称: API_CacheDmaFree
** 功能描述: 归还一块非缓冲的内存
** 输 入  :
**           pvBuf                         开辟时的首地址
** 输 出  : NONE
*********************************************************************************************************/
VOID    API_CacheDmaFree (PVOID  pvBuf)
{if (_G_cacheopLib.CACHEOP_pfuncDmaFree) {_G_cacheopLib.CACHEOP_pfuncDmaFree(pvBuf);} else {__KHEAP_FREE(pvBuf);}
}
/*********************************************************************************************************
** 函数名称: API_CacheDmaFlush
** 功能描述: DMA 区域 CACHE 将所有或者指定的数据项清空(回写入内存)
** 输 入  : pvAdrs                        虚拟地址
**           stBytes                       长度
** 输 出  : ERROR_NONE
*********************************************************************************************************/
INT    API_CacheDmaFlush (PVOID  pvAdrs, size_t  stBytes)
{return  ((_G_cacheopLib.CACHEOP_pfuncDmaMalloc == LW_NULL) ?(API_CacheFlush(DATA_CACHE, pvAdrs, stBytes)) : (ERROR_NONE));
}
/*********************************************************************************************************
** 函数名称: API_CacheDmaInvalidate
** 功能描述: DMA 区域 CACHE 使部分或全部表项无效(访问不命中)
** 输 入  : pvAdrs                        虚拟地址
**           stBytes                       长度
** 输 出  : ERROR_NONE
*********************************************************************************************************/
INT    API_CacheDmaInvalidate (PVOID  pvAdrs, size_t  stBytes)
{return  ((_G_cacheopLib.CACHEOP_pfuncDmaMalloc == LW_NULL) ?(API_CacheInvalidate(DATA_CACHE, pvAdrs, stBytes)) : (ERROR_NONE));
}
/*********************************************************************************************************
** 函数名称: API_CacheDmaClear
** 功能描述: DMA 区域 CACHE 使部分或全部清空(回写内存)并无效(访问不命中)
** 输 入  : pvAdrs                        虚拟地址
**           stBytes                       长度
** 输 出  : ERROR_NONE
*********************************************************************************************************/
INT    API_CacheDmaClear (PVOID  pvAdrs, size_t  stBytes)
{return  ((_G_cacheopLib.CACHEOP_pfuncDmaMalloc == LW_NULL) ?(API_CacheClear(DATA_CACHE, pvAdrs, stBytes)) : (ERROR_NONE));
}

arch层实现源码

以arm体系结构为例,其他体系结构类似。

#if LW_CFG_VMM_EN > 0pcacheop->CACHEOP_pfuncDmaMalloc      = API_VmmDmaAlloc;pcacheop->CACHEOP_pfuncDmaMallocAlign = API_VmmDmaAllocAlign;pcacheop->CACHEOP_pfuncDmaFree        = API_VmmDmaFree;
#endif
/*********************************************************************************************************
** 函数名称: API_VmmDmaAlloc
** 功能描述: 从物理内存区分配连续的物理分页, 主要用于 DMA 连续物理内存操作.
** 输 入  : stSize     需要分配的内存大小
** 输 出  : 连续分页首地址 (物理地址, 此地址对应的物理地址存在于 LW_ZONE_ATTR_DMA 区域内)
*********************************************************************************************************/
PVOID  API_VmmDmaAlloc (size_t  stSize)
{ULONG   ulFlags;#if LW_CFG_CACHE_EN > 0if (API_CacheGetMode(DATA_CACHE) & CACHE_SNOOP_ENABLE) {ulFlags = LW_VMM_FLAG_RDWR;} else
#endif                                                                  /*  LW_CFG_CACHE_EN > 0         */{ulFlags = LW_VMM_FLAG_DMA;}return  (API_VmmDmaAllocAlignWithFlags(stSize, LW_CFG_VMM_PAGE_SIZE, ulFlags));
}
/*********************************************************************************************************
** 函数名称: API_VmmDmaAllocAlign
** 功能描述: 从物理内存区分配连续的物理分页, 主要用于 DMA 连续物理内存操作.(可指定内存关系)
** 输 入  : stSize     需要分配的内存大小
**           stAlign    对齐关系
** 输 出  : 连续分页首地址 (物理地址, 此地址对应的物理地址存在于 LW_ZONE_ATTR_DMA 区域内)
*********************************************************************************************************/
PVOID  API_VmmDmaAllocAlign (size_t  stSize, size_t  stAlign)
{ULONG   ulFlags;#if LW_CFG_CACHE_EN > 0if (API_CacheGetMode(DATA_CACHE) & CACHE_SNOOP_ENABLE) {ulFlags = LW_VMM_FLAG_RDWR;} else
#endif                                                                  /*  LW_CFG_CACHE_EN > 0         */{ulFlags = LW_VMM_FLAG_DMA;}return  (API_VmmDmaAllocAlignWithFlags(stSize, stAlign, ulFlags));
}
/*********************************************************************************************************
** 函数名称: API_VmmDmaAllocAlignWithFlags
** 功能描述: 从物理内存区分配连续的物理分页, 主要用于 DMA 连续物理内存操作.(可指定内存关系)
** 输 入  : stSize     需要分配的内存大小
**           stAlign    对齐关系
**           ulFlags    映射类型
** 输 出  : 连续分页首地址 (物理地址, 此地址对应的物理地址存在于 LW_ZONE_ATTR_DMA 区域内)
*********************************************************************************************************/
PVOID  API_VmmDmaAllocAlignWithFlags (size_t  stSize, size_t  stAlign, ULONG  ulFlags)
{REGISTER ULONG          ulPageNum = (ULONG) (stSize >> LW_CFG_VMM_PAGE_SHIFT);REGISTER size_t         stExcess  = (size_t)(stSize & ~LW_CFG_VMM_PAGE_MASK);REGISTER PLW_VMM_PAGE   pvmpage;ULONG          ulZoneIndex;ULONG          ulError;if (stAlign & (stAlign - 1)) {return  (LW_NULL);}if (stAlign < LW_CFG_VMM_PAGE_SIZE) {stAlign = LW_CFG_VMM_PAGE_SIZE;}if (stExcess) {ulPageNum++;}if (ulPageNum < 1) {_ErrorHandle(EINVAL);return  (LW_NULL);}pvmpage = __vmmPhysicalPageAllocAlign(ulPageNum, stAlign, LW_ZONE_ATTR_DMA,&ulZoneIndex);                /*  分配连续物理页面            */ulError = __vmmLibPageMap(pvmpage->PAGE_ulPageAddr,                 /*  不使用 CACHE                */pvmpage->PAGE_ulPageAddr,ulPageNum, ulFlags);                                 /*  映射逻辑物理同一地址        */pvmpage->PAGE_ulMapPageAddr = pvmpage->PAGE_ulPageAddr;pvmpage->PAGE_ulFlags = ulFlags;                                    /*  记录分页类型                */__areaPhysicalInsertPage(ulZoneIndex, pvmpage->PAGE_ulPageAddr, pvmpage);        /*  插入物理空间反查表          */return  ((PVOID)pvmpage->PAGE_ulPageAddr);                          /*  直接返回物理内存地址        */
}

SylixOS中的动态内存分配【14】--- cache API中的非缓存内存分配接口实现原理相关推荐

  1. 服务器无法通过系统非页面,服务器无法通过系统非页面共享区来进行分配,因为服务器已达非页面共享分配的配置极限。...

    局域网共享无法访问,查看系统日志,会有这个出错信息: 服务器无法通过系统非页面共享区来进行分配,因为服务器已达非页面共享分配的配置极限. System - Provider [ Name] srv - ...

  2. 怎么把dll库写成MATLAB接口,如何在Matlab中应用动态连接库接口技术

    1 引言 Matlab是当前应用最为广泛的数学软件,具有强大的数值计算.数据分析处理.系统 分析.图形显示甚至符号运算等功能.利用这一完整的数学平台,用户可以快速实现十分 复杂的功能,极大地提高工程分 ...

  3. 在静态SQL中实现动态WHERE子句

    目录 介绍 实现动态WHERE-Clause 使用COALESCE 使用ISNULL 使用CASE 替代方案 结论 本文介绍了在静态SQL中实现动态WHERE-Clause的不同方法. 下载演示SQL ...

  4. java堆和非堆_java 堆与非堆 内存

    堆(Heap)和非堆(Non-heap)内存 按照官方的说法:"Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配.堆是在 Java 虚拟机启动时创建的.&q ...

  5. java 增加内存_如何增加java虚拟机可以使用的最大内存

    java虚拟机可使用的最大内存是有限制的,缺省值通常为64MB或128MB. 如果一个应用程序为了提高性能而把数据加载内存中而占用较大的内存,比如超过了默认的最大值128MB,需要加大java虚拟机可 ...

  6. Java堆内存Heap与非堆内存Non-Heap简介和设置

    Java 开发对JVM(Java虚拟机)的了解很有必要,网上看到,收集整理转载一下,方便日后的懒人计划 堆(Heap)和非堆(Non-heap)内存 按照官方的说法:"Java 虚拟机具有一 ...

  7. Java堆内存Heap与非堆内存Non-Heap

    堆(Heap)和非堆(Non-heap)内存     按照官方的说法:"Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配.堆是在 Java 虚拟机启动时创建 ...

  8. java non-heap_Java堆内存Heap与非堆内存Non-Heap简介和设置

    Java 开发对JVM(Java虚拟机)的了解很有必要,网上看到,收集整理转载一下,方便日后的懒人计划 堆(Heap)和非堆(Non-heap)内存 按照官方的说法:"Java 虚拟机具有一 ...

  9. C++中的动态内存分配

    1.Cpp中的内存分配 了解动态内存在C++中是如何工作的是成为一名合格的C++程序员必不可少的.C++程序中的内存分为两个部分: 栈:在函数内部声明的所有变量都将占用栈内存. 堆:这是程序中未使用的 ...

最新文章

  1. tomcat安装apr优化
  2. Python - Windows系统下安装使用virtualenv
  3. nginx upstream配置_Prometheus快速监控Nginx
  4. js,jquery字符串转换json,兼容各种浏览器
  5. 360要在A股上市 华泰联合证券已签订IPO辅导协议
  6. Web Hacking 101 中文版 八、跨站请求伪造
  7. java 获取线程某个_Java中如何唤醒“指定的“某个线程
  8. 创业过程中一定会引进纯资金投资人
  9. ibavformat.so.57: cannot open shared object file: No such file or directory
  10. flowchart流程图编程语言下载_c语言流程图生成器下载
  11. 干货 | 推荐几款实用的思维导图工具
  12. 修改窗口的风格ModifyStyle
  13. excel下拉列表多选框_将列表框添加到Excel工作表
  14. 微信分享带图片,描述(php版)
  15. NET新手遭遇问题(九)
  16. 在docker容器中操作es,并给es7.6添加用户鉴权设置密码
  17. 巨人10Q4财报:营收3.6亿元环比增8.7%
  18. PotPlayer打开视频没声音,显示DirectX有问题或者音频禁用怎么办?
  19. Keil MDK生成LIB库以及使用LIB库
  20. “比特”与“瓦特”深度融合,云计算驶向绿色低碳快车道

热门文章

  1. 做淘客你必须知道的引流技巧和套路
  2. MCE公司:新型靶向RAS突变的共价抑制剂
  3. 【ccpc2018吉林F题】THE HERMIT (思维)
  4. 相机卡里的照片删除了怎么恢复
  5. xposed输出qq加密前明文数据
  6. 林瞥网,一个关注站长导航工具网站
  7. Electron入门
  8. Tomcat集群同步原理
  9. 嵌入式驱动编写-LCD驱动程序
  10. 专利的权利范围怎么理解?