Fix the memheap_realloc issue

This commit is contained in:
Bernard Xiong 2013-06-03 06:44:35 +08:00
parent 3c04d0b0a0
commit d80a471680
4 changed files with 128 additions and 66 deletions

View File

@ -9,6 +9,7 @@
* Date Author Notes
* 2013-04-15 Bernard the first version
* 2013-05-05 Bernard remove CRC for ramfs persistence
* 2013-05-22 Bernard fix the no entry issue.
*/
#include <rtthread.h>
@ -217,6 +218,7 @@ int dfs_ramfs_open(struct dfs_fd *file)
/* add to the root directory */
rt_list_insert_after(&(ramfs->root.list), &(dirent->list));
}
else return -DFS_STATUS_ENOENT;
}
/* Creates a new file. If the file is existing, it is truncated and overwritten. */

View File

@ -454,7 +454,8 @@ static long _list_device(struct rt_list_node *list)
"SPI Bus",
"SPI Device",
"SDIO Bus",
"PM Pseudo Device",
"PM Pseudo Device",
"Miscellaneous Device",
"Unknown"
};

View File

@ -145,17 +145,6 @@ typedef rt_base_t rt_off_t; /**< Type for offset */
#define ALIGN(n) __declspec(align(n))
#define rt_inline static __inline
#define RTT_API
#elif defined (__TI_COMPILER_VERSION__)
/* The way that TI compiler set section is different from other(at least
* GCC and MDK) compilers. See ARM Optimizing C/C++ Compiler 5.9.3 for more
* details. */
#define SECTION(x)
#define UNUSED
#define ALIGN(n)
#define rt_inline static inline
#define RTT_API
#else
#error not supported tool chain
#endif
/* event length */
@ -175,6 +164,10 @@ typedef rt_base_t rt_off_t; /**< Type for offset */
#define RT_KERNEL_FREE(ptr) rt_free(ptr)
#endif
#ifndef RT_KERNEL_REALLOC
#define RT_KERNEL_REALLOC(ptr, size) rt_realloc(ptr, size)
#endif
/**
* @addtogroup Error
*/
@ -596,11 +589,11 @@ typedef struct rt_messagequeue *rt_mq_t;
struct rt_memheap_item
{
rt_uint32_t magic; /**< magic number for memheap */
struct rt_memheap *pool_ptr; /**< point of pool */
struct rt_memheap_item *next; /**< next memheap item */
struct rt_memheap_item *prev; /**< prev memheap item */
struct rt_memheap *pool_ptr; /**< point of pool */
struct rt_memheap_item *next_free; /**< next free memheap item */
struct rt_memheap_item *prev_free; /**< prev free memheap item */
};
@ -679,6 +672,7 @@ enum rt_device_class_type
RT_Device_Class_SPIDevice, /**< SPI device */
RT_Device_Class_SDIO, /**< SDIO bus device */
RT_Device_Class_PM, /**< PM pseudo device */
RT_Device_Class_Miscellaneous, /**< Miscellaneous device */
RT_Device_Class_Unknown /**< unknown device */
};
@ -754,11 +748,6 @@ struct rt_device
rt_size_t (*write) (rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size);
rt_err_t (*control)(rt_device_t dev, rt_uint8_t cmd, void *args);
#ifdef RT_USING_DEVICE_SUSPEND
rt_err_t (*suspend) (rt_device_t dev);
rt_err_t (*resumed) (rt_device_t dev);
#endif
void *user_data; /**< device private data */
};

View File

@ -14,6 +14,7 @@
* 2012-12-29 Bernard memheap can be used as system heap.
* change mutex lock to semaphore lock.
* 2013-04-10 Bernard add rt_memheap_realloc function.
* 2013-05-24 Bernard fix the rt_memheap_realloc issue.
*/
#include <rthw.h>
@ -165,10 +166,7 @@ void *rt_memheap_alloc(struct rt_memheap *heap, rt_uint32_t size)
while (header_ptr != heap->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;
free_size = MEMITEM_SIZE(header_ptr);
if (free_size < size)
{
/* move to next free memory block */
@ -280,22 +278,113 @@ RTM_EXPORT(rt_memheap_alloc);
void *rt_memheap_realloc(struct rt_memheap* heap, void* ptr, rt_size_t newsize)
{
void* new_ptr;
rt_err_t result;
rt_size_t oldsize;
struct rt_memheap_item *header_ptr;
struct rt_memheap_item *new_ptr;
if (newsize == 0)
{
rt_memheap_free(ptr);
return RT_NULL;
}
/* align allocated size */
newsize = RT_ALIGN(newsize, RT_ALIGN_SIZE);
if (newsize < RT_MEMHEAP_MINIALLOC)
newsize = RT_MEMHEAP_MINIALLOC;
if (ptr == RT_NULL)
{
return rt_memheap_alloc(heap, newsize);
}
new_ptr = rt_memheap_alloc(heap, newsize);
if (new_ptr == RT_NULL) return RT_NULL;
/* get memory block header and get the size of memory block */
header_ptr = (struct rt_memheap_item*)((rt_uint8_t *)ptr -
RT_MEMHEAP_SIZE);
oldsize = MEMITEM_SIZE(header_ptr);
/* re-allocate memory */
if (newsize > oldsize)
{
void* new_ptr;
/* re-allocate a memory block */
new_ptr = (void*)rt_memheap_alloc(heap, newsize);
if (new_ptr != RT_NULL)
{
rt_memcpy(new_ptr, ptr, oldsize < newsize ? oldsize : newsize);
rt_memheap_free(ptr);
}
rt_memcpy(new_ptr, ptr, newsize);
return new_ptr;
return new_ptr;
}
/* lock memheap */
result = rt_sem_take(&(heap->lock), RT_WAITING_FOREVER);
if (result != RT_EOK)
{
rt_set_errno(result);
return RT_NULL;
}
/* split the block. */
new_ptr = (struct rt_memheap_item *)
(((rt_uint8_t *)header_ptr) + newsize + RT_MEMHEAP_SIZE);
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
("split: block[0x%08x] nextm[0x%08x] prevm[0x%08x] to new[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 = heap;
/* 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;
/* determine if the block can be merged with the next neighbor. */
if (!RT_MEMHEAP_IS_USED(new_ptr->next))
{
struct rt_memheap_item *free_ptr;
/* merge block with next neighbor. */
free_ptr = new_ptr->next;
heap->available_size = heap->available_size - MEMITEM_SIZE(free_ptr);
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
("merge: right node 0x%08x, next_free 0x%08x, prev_free 0x%08x",
header_ptr, header_ptr->next_free, header_ptr->prev_free));
free_ptr->next->prev = new_ptr;
new_ptr->next = free_ptr->next;
/* remove free ptr from free list */
free_ptr->next_free->prev_free = free_ptr->prev_free;
free_ptr->prev_free->next_free = free_ptr->next_free;
}
/* insert the split block to free list */
new_ptr->next_free = heap->free_list->next_free;
new_ptr->prev_free = heap->free_list;
heap->free_list->next_free->prev_free = new_ptr;
heap->free_list->next_free = new_ptr;
RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("new free ptr: next_free 0x%08x, prev_free 0x%08x",
new_ptr->next_free,
new_ptr->prev_free));
/* increment the available byte count. */
heap->available_size = heap->available_size + MEMITEM_SIZE(new_ptr);
/* release lock */
rt_sem_release(&(heap->lock));
/* return the old memory block */
return ptr;
}
RTM_EXPORT(rt_memheap_realloc);
@ -326,13 +415,11 @@ void rt_memheap_free(void *ptr)
if (result != RT_EOK)
{
rt_set_errno(result);
return ;
}
/* Mark the memory as available. */
header_ptr->magic &= ~RT_MEMHEAP_USED;
/* Adjust the available number of bytes. */
heap->available_size = heap->available_size + MEMITEM_SIZE(header_ptr);
@ -409,7 +496,7 @@ void rt_system_heap_init(void *begin_addr, void *end_addr)
void *rt_malloc(rt_size_t size)
{
void* ptr;
/* try to allocate in system heap */
ptr = rt_memheap_alloc(&_heap, size);
if (ptr == RT_NULL)
@ -451,48 +538,31 @@ RTM_EXPORT(rt_free);
void *rt_realloc(void *rmem, rt_size_t newsize)
{
rt_size_t size;
void *nmem = RT_NULL;
void *new_ptr;
struct rt_memheap_item *header_ptr;
RT_DEBUG_NOT_IN_INTERRUPT;
if (rmem == RT_NULL) return rt_malloc(newsize);
/* alignment size */
newsize = RT_ALIGN(newsize, RT_ALIGN_SIZE);
/* allocate a memory */
if (rmem == RT_NULL)
{
return rt_malloc(newsize);
}
/* release memory */
if (newsize == 0)
{
rt_free(rmem);
return RT_NULL;
}
/* get old memory item */
header_ptr = (struct rt_memheap_item *)((rt_uint8_t *)rmem - RT_MEMHEAP_SIZE);
size = MEMITEM_SIZE(header_ptr);
/* re-allocate memory */
if (newsize > size || newsize < size - RT_MEMHEAP_SIZE)
{
/* re-allocate a memory block */
nmem = (void*)rt_malloc(newsize);
if (nmem != RT_NULL)
{
rt_memcpy(nmem, rmem, size < newsize ? size : newsize);
rt_free(rmem);
}
return nmem;
}
new_ptr = rt_memheap_realloc(header_ptr->pool_ptr, rmem, newsize);
if (new_ptr == RT_NULL && newsize != 0)
{
/* allocate memory block from other memheap */
new_ptr = rt_malloc(newsize);
if (new_ptr != RT_NULL && rmem != RT_NULL)
{
rt_size_t oldsize;
/* use the old memory block */
return rmem;
/* get the size of old memory block */
oldsize = MEMITEM_SIZE(header_ptr);
if (newsize > oldsize) rt_memcpy(new_ptr, rmem, oldsize);
else rt_memcpy(new_ptr, rmem, newsize);
}
}
return new_ptr;
}
RTM_EXPORT(rt_realloc);