Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
RT-Thread发布
memheap没有使用锁机制,多线程使用出错
发布于 2012-10-15 10:07:48 浏览:5431
订阅该版
memheap的alloc和free中没有使用锁机制,使得memheap在多线程使用中出现了很多奇怪的问题,不知道是原始设计就是这样还是bug
查看更多
8
个回答
默认排序
按发布时间排序
bernard
2012-10-15
这家伙很懒,什么也没写!
请提供下测试代码。
www220
2012-10-15
这家伙很懒,什么也没写!
代码比较复杂就不全部贴出了,我使用和lwip不想他无限制的使用ram,就使用memheap函数划分出一块固定大小的内存200k供lwip使用,同时修改lwip中的宏定义 ``` #define mem_malloc(x) rt_memheap_alloc(&lwip_memheap,x) #define mem_free rt_memheap_free #define mem_calloc rt_xxxx ``` 测试时发现大数据量的时候经常性的断言或硬件错误,原来使用rt_malloc时是没有问题的,后比对rt_malloc和rt_memheap_alloc代码发现rt_memheap_alloc代码中没有使用锁机制,比对rt_malloc增加锁机制后,测试正常
bernard
2012-10-17
这家伙很懒,什么也没写!
这部分确认了,会在1.1.0版本中修改完善。
www220
2012-10-23
这家伙很懒,什么也没写!
更新了最新的rt-thread,里面memheap增加了锁机制,测试发现还是不定时出现断言和硬件错误,一下代码是我修改的memheap测试时没有相关问题,比对代码也没有发现什么问题,求解决 ``` /* * File : memheap.c * This file is part of RT-Thread RTOS * COPYRIGHT (C) 2012, RT-Thread Development Team * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rt-thread.org/license/LICENSE * * Change Logs: * Date Author Notes * 2012-04-10 Bernard first implementation */ #include
#ifdef RT_USING_MEMHEAP /* dynamic pool magic and mask */ #define RT_MEMHEAP_MAGIC 0x1ea01ea0 #define RT_MEMHEAP_MASK 0xfffffffe #define RT_MEMHEAP_USED 0x01 #define RT_MEMHEAP_FREED 0x00 #define RT_MEMHEAP_IS_USED(i) ((i)->magic & RT_MEMHEAP_USED) #define RT_MEMHEAP_MINIALLOC 12 #define RT_MEMHEAP_SIZE RT_ALIGN(sizeof(struct rt_memheap_item), RT_ALIGN_SIZE) static struct rt_semaphore memheap_sem; /* * The initialized memory pool will be: * +-----------------------------------+--------------------------+ * | whole freed memory block | Used Memory Block Tailer | * +-----------------------------------+--------------------------+ * * block_list --> whole freed memory block * * The length of Used Memory Block Tailer is 0, which is prevents block merging across list */ rt_err_t rt_memheap_init(struct rt_memheap *memheap, const char *name, void *start_addr, rt_uint32_t size) { struct rt_memheap_item *item; RT_ASSERT(memheap != RT_NULL); /* initialize pool object */ rt_object_init(&(memheap->parent), RT_Object_Class_MemHeap, name); memheap->start_addr = start_addr; memheap->pool_size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE); memheap->available_size = memheap->pool_size - (2 * RT_MEMHEAP_SIZE); /* initialize the free list header */ item = &(memheap->free_header); item->magic = RT_MEMHEAP_MAGIC; item->pool_ptr = memheap; item->next = RT_NULL; item->prev = RT_NULL; item->next_free = item; item->prev_free = item; /* set the free list to free list header */ memheap->free_list = item; /* initialize the first big memory block */ item = (struct rt_memheap_item *)start_addr; item->magic = RT_MEMHEAP_MAGIC; item->pool_ptr = memheap; item->next = RT_NULL; item->prev = RT_NULL; item->next_free = item; item->prev_free = item; item->next = (struct rt_memheap_item *) ((rt_uint8_t *)item + memheap->available_size + RT_MEMHEAP_SIZE); item->prev = item->next; /* block list header */ memheap->block_list = item; /* place the big memory block to free list */ item->next_free = memheap->free_list->next_free; item->prev_free = memheap->free_list; memheap->free_list->next_free->prev_free = item; memheap->free_list->next_free = item; /* move to the end of memory pool to build a small tailer block, which prevents block merging */ item = item->next; /* it's a used memory block */ item->magic = RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED; item->pool_ptr = memheap; item->next = (struct rt_memheap_item *)start_addr; item->prev = (struct rt_memheap_item *)start_addr; /* not in free list */ item->next_free = item->prev_free = RT_NULL; rt_sem_init(&memheap_sem, "memheap", 1, RT_IPC_FLAG_FIFO); RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("memory heap: start addr 0x%08x, size %d, free list header 0x%08x", start_addr, size, &(memheap->free_header))); return RT_EOK; } RTM_EXPORT(rt_memheap_init); rt_err_t rt_memheap_detach(struct rt_memheap *heap) { rt_object_detach(&(heap->parent)); /* Return a successful completion. */ return RT_EOK; } RTM_EXPORT(rt_memheap_detach); void *rt_memheap_alloc(struct rt_memheap *pool_ptr, rt_uint32_t size) { rt_uint32_t free_size; struct rt_memheap_item *header_ptr; RT_ASSERT(pool_ptr != RT_NULL); if (size == 0) return RT_NULL; /* align allocated size */ size = RT_ALIGN(size, RT_ALIGN_SIZE); if (size < RT_MEMHEAP_MINIALLOC) size = RT_MEMHEAP_MINIALLOC; RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("allocate %d", size)); /* take memory semaphore */ rt_sem_take(&memheap_sem, RT_WAITING_FOREVER); if (size < pool_ptr->available_size) { /* search on free list */ free_size = 0; /* get the first free memory block */ header_ptr = pool_ptr->free_list->next_free; while (header_ptr != pool_ptr->free_list && free_size < size) { /* get current freed memory block size */ free_size = (rt_uint32_t)(header_ptr->next) - (rt_uint32_t)header_ptr - RT_MEMHEAP_SIZE; if (free_size < size) { /* move to next free memory block */ header_ptr = header_ptr->next_free; } } /* determine if the memory is available. */ if (free_size >= size) { /* a block that satisfies the request has been found. */ /* determine if the block needs to be split. */ if (free_size >= (size + RT_MEMHEAP_SIZE + RT_MEMHEAP_MINIALLOC)) { struct rt_memheap_item *new_ptr; /* split the block. */ new_ptr = (struct rt_memheap_item *)(((rt_uint8_t *)header_ptr) + size + RT_MEMHEAP_SIZE); RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("split: h[0x%08x] nm[0x%08x] pm[0x%08x] to n[0x%08x]", header_ptr, header_ptr->next, header_ptr->prev, new_ptr)); /* mark the new block as a memory block and freed. */ new_ptr->magic = RT_MEMHEAP_MAGIC; /* put the pool pointer into the new block. */ new_ptr->pool_ptr = pool_ptr; /* break down the block list */ new_ptr->prev = header_ptr; new_ptr->next = header_ptr->next; header_ptr->next->prev = new_ptr; header_ptr->next = new_ptr; /* remove header ptr from free list */ header_ptr->next_free->prev_free = header_ptr->prev_free; header_ptr->prev_free->next_free = header_ptr->next_free; header_ptr->next_free = RT_NULL; header_ptr->prev_free = RT_NULL; /* insert new_ptr to free list */ new_ptr->next_free = pool_ptr->free_list->next_free; new_ptr->prev_free = pool_ptr->free_list; pool_ptr->free_list->next_free->prev_free = new_ptr; pool_ptr->free_list->next_free = new_ptr; RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("new ptr: nf 0x%08x, pf 0x%08x", new_ptr->next_free, new_ptr->prev_free)); /* decrement the available byte count. */ pool_ptr->available_size = pool_ptr->available_size - size - RT_MEMHEAP_SIZE; } else { /* decrement the entire free size from the available bytes count. */ pool_ptr->available_size = pool_ptr->available_size - free_size; /* remove header_ptr from free list */ RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("one block: h[0x%08x], nf 0x%08x, pf 0x%08x", header_ptr, header_ptr->next_free, header_ptr->prev_free)); header_ptr->next_free->prev_free = header_ptr->prev_free; header_ptr->prev_free->next_free = header_ptr->next_free; header_ptr->next_free = RT_NULL; header_ptr->prev_free = RT_NULL; } /* Mark the allocated block as not available. */ header_ptr->magic |= RT_MEMHEAP_USED; rt_sem_release(&memheap_sem); /* Return a memory address to the caller. */ RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("am: m[0x%08x], h[0x%08x], size: %d", (void *)((rt_uint8_t *)header_ptr + RT_MEMHEAP_SIZE), header_ptr, size); return (void *)((rt_uint8_t *)header_ptr + RT_MEMHEAP_SIZE)); } } rt_sem_release(&memheap_sem); RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("allocate memory: failed ")); /* Return the completion status. */ return RT_NULL; } RTM_EXPORT(rt_memheap_alloc); void rt_memheap_free(void *ptr) { struct rt_memheap *pool_ptr; struct rt_memheap_item *header_ptr, *new_ptr; rt_uint32_t insert_header; if (ptr == RT_NULL) return; /* set initial status as OK */ insert_header = 1; new_ptr = RT_NULL; header_ptr = (struct rt_memheap_item *)((rt_uint8_t *)ptr - RT_MEMHEAP_SIZE); RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("free memory: m[0x%08x], h[0x%08x]", ptr, header_ptr)); /* protect the heap from concurrent access */ rt_sem_take(&memheap_sem, RT_WAITING_FOREVER); /* check magic */ RT_ASSERT((header_ptr->magic & RT_MEMHEAP_MASK) == RT_MEMHEAP_MAGIC); /* get pool ptr */ pool_ptr = header_ptr->pool_ptr; /* Mark the memory as available. */ header_ptr->magic &= ~RT_MEMHEAP_USED; /* Adjust the available number of bytes. */ pool_ptr->available_size = pool_ptr->available_size + ((rt_uint32_t)(header_ptr->next) - (rt_uint32_t)header_ptr) - RT_MEMHEAP_SIZE; /* Determine if the block can be merged with the previous neighbor. */ if (!RT_MEMHEAP_IS_USED(header_ptr->prev)) { RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("merge: left node 0x%08x", header_ptr->prev)); /* adjust the available number of bytes. */ pool_ptr->available_size = pool_ptr->available_size + RT_MEMHEAP_SIZE; /* yes, merge block with previous neighbor. */ (header_ptr->prev)->next = header_ptr->next; (header_ptr->next)->prev = header_ptr->prev; /* move header pointer to previous. */ header_ptr = header_ptr->prev; /* don't insert header to free list */ insert_header = 0; } /* determine if the block can be merged with the next neighbor. */ if (!RT_MEMHEAP_IS_USED(header_ptr->next)) { /* adjust the available number of bytes. */ pool_ptr->available_size = pool_ptr->available_size + RT_MEMHEAP_SIZE; /* merge block with next neighbor. */ new_ptr = header_ptr->next; RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("merge: right node 0x%08x, nf 0x%08x, pf 0x%08x", new_ptr, new_ptr->next_free, new_ptr->prev_free)); new_ptr->next->prev = header_ptr; header_ptr->next = new_ptr->next; /* remove new ptr from free list */ new_ptr->next_free->prev_free = new_ptr->prev_free; new_ptr->prev_free->next_free = new_ptr->next_free; } if (insert_header) { /* no left merge, insert to free list */ header_ptr->next_free = pool_ptr->free_list->next_free; header_ptr->prev_free = pool_ptr->free_list; pool_ptr->free_list->next_free->prev_free = header_ptr; pool_ptr->free_list->next_free = header_ptr; RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("insert to free list: nf 0x%08x, pf 0x%08x", header_ptr->next_free, header_ptr->prev_free)); } rt_sem_release(&memheap_sem); } RTM_EXPORT(rt_memheap_free); #endif ```
www220
2012-10-25
这家伙很懒,什么也没写!
经过比对测试发现,锁释放太早,应该在 ``` header_ptr->magic |= RT_MEMHEAP_USED; ``` 这句话以后再释放,因为mem在free的时候会判断前后的magic是否为USED进行相关的合并 不知道是否这个问题
bernard
2012-10-25
这家伙很懒,什么也没写!
可能是的,这个东西还比较难测试,需要大量的线程抢占情况下才能够测试出来(例如中断比较多的时候)。
prife
2012-10-25
这家伙很懒,什么也没写!
楼主,可以用patch的方式提交补丁,svn工具可以生成patch的,在修改的文件上右击右键菜单里仔细找下。这样比较方便查阅修改。 楼主做的相当不错,支持一下
撰写答案
登录
注册新账号
关注者
0
被浏览
5.4k
关于作者
www220
这家伙很懒,什么也没写!
提问
2
回答
25
被采纳
0
关注TA
发私信
相关问题
1
RT-Thread单内核v0.2.2正式版
2
[发布] RT-Thread RTOS v0.2.3版本
3
RT-Thread 0.3.0 beta
4
RT-Thread/STM32 0.3.0 RC1发布
5
RT-Thread/LM3S 0.3.0 RC1版发布
6
建议弄个MIPS版本的。龙芯上用。
7
开源实时操作系统RT-Thread 0.3.0正式版发布
8
关于RT-THREAD的UDP讨论
9
这里是BUG回报板块!
10
rt-thread stm32 0.3.0 rc1 网络问题
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
rt-thread 小内存算法源码分析
2
env中添加lvgl软件包后,keil编译包--c99错误
3
【NXP-MCXA153】 定时器驱动移植
4
GD32F450 看门狗驱动适配
5
【NXP-MCXA153】看门狗驱动移植
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
PWM
freemodbus
flash
cubemx
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
编译报错
Debug
rt_mq_消息队列_msg_queue
SFUD
keil_MDK
msh
ulog
C++_cpp
MicroPython
本月问答贡献
踩姑娘的小蘑菇
7
个答案
2
次被采纳
a1012112796
18
个答案
1
次被采纳
红枫
5
个答案
1
次被采纳
Ryan_CW
5
个答案
1
次被采纳
张世争
4
个答案
1
次被采纳
本月文章贡献
YZRD
3
篇文章
6
次点赞
catcatbing
3
篇文章
6
次点赞
lizimu
2
篇文章
11
次点赞
qq1078249029
2
篇文章
2
次点赞
xnosky
2
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部