Fix the memheap_realloc issue
This commit is contained in:
parent
3c04d0b0a0
commit
d80a471680
|
@ -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. */
|
||||
|
|
|
@ -455,6 +455,7 @@ static long _list_device(struct rt_list_node *list)
|
|||
"SPI Device",
|
||||
"SDIO Bus",
|
||||
"PM Pseudo Device",
|
||||
"Miscellaneous Device",
|
||||
"Unknown"
|
||||
};
|
||||
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
156
src/memheap.c
156
src/memheap.c
|
@ -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;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
|
@ -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;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
if (rmem == RT_NULL) return rt_malloc(newsize);
|
||||
|
||||
/* 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)
|
||||
|
||||
new_ptr = rt_memheap_realloc(header_ptr->pool_ptr, rmem, newsize);
|
||||
if (new_ptr == RT_NULL && newsize != 0)
|
||||
{
|
||||
/* re-allocate a memory block */
|
||||
nmem = (void*)rt_malloc(newsize);
|
||||
if (nmem != RT_NULL)
|
||||
/* allocate memory block from other memheap */
|
||||
new_ptr = rt_malloc(newsize);
|
||||
if (new_ptr != RT_NULL && rmem != RT_NULL)
|
||||
{
|
||||
rt_memcpy(nmem, rmem, size < newsize ? size : newsize);
|
||||
rt_free(rmem);
|
||||
rt_size_t oldsize;
|
||||
|
||||
/* 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 nmem;
|
||||
}
|
||||
|
||||
/* use the old memory block */
|
||||
return rmem;
|
||||
return new_ptr;
|
||||
}
|
||||
RTM_EXPORT(rt_realloc);
|
||||
|
||||
|
|
Loading…
Reference in New Issue