Przeglądaj źródła

Fix the memheap_realloc issue

Bernard Xiong 12 lat temu
rodzic
commit
d80a471680
4 zmienionych plików z 128 dodań i 66 usunięć
  1. 2 0
      components/dfs/filesystems/ramfs/dfs_ramfs.c
  2. 2 1
      components/finsh/cmd.c
  3. 7 18
      include/rtdef.h
  4. 117 47
      src/memheap.c

+ 2 - 0
components/dfs/filesystems/ramfs/dfs_ramfs.c

@@ -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. */

+ 2 - 1
components/finsh/cmd.c

@@ -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"
     };
 

+ 7 - 18
include/rtdef.h

@@ -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 */
 };
 

+ 117 - 47
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;
+        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;
-
-    /* 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);
+	if (rmem == RT_NULL) return rt_malloc(newsize);
 
-        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;
+
+			/* 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);
+		}
+	}
 
-    /* use the old memory block */
-    return rmem;
+	return new_ptr;
 }
 RTM_EXPORT(rt_realloc);