os_memory.c
2026/7/19大约 8 分钟附录源码附录
os_memory.c
路径: kernel\source\os_memory.c
/**
***********************************************************************************************************************
* Copyright (c) 2020, China Mobile Communications Group Co.,Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* @file os_memory.c
*
* @brief This file implements default memory management and mulitiheap management.
*
* @revision
* Date Author Notes
* 2020-11-18 OneOS team First version.
***********************************************************************************************************************
*/
#include <string.h>
#include <os_types.h>
#include <os_stddef.h>
#include <os_errno.h>
#include <os_memory.h>
#include <os_spinlock.h>
#include "os_kernel_internal.h"
#define MEM_TAG "MEM"
struct alg_init_func
{
enum os_mem_alg mem_alg;
void (*mem_init)(struct heap_mem *h_mem, void *start_addr, os_size_t size);
};
#ifdef OS_USING_ALG_FIRSTFIT
extern void k_firstfit_mem_init(struct heap_mem *h_mem, void *start_addr, os_size_t size);
#endif
#ifdef OS_USING_ALG_BUDDY
extern void k_buddy_mem_init(struct heap_mem *h_mem, void *start_addr, os_size_t size);
#endif
static struct alg_init_func alg_init_table[] = {
#ifdef OS_USING_ALG_FIRSTFIT
{OS_MEM_ALG_FIRSTFIT, k_firstfit_mem_init},
#endif
#ifdef OS_USING_ALG_BUDDY
{OS_MEM_ALG_BUDDY, k_buddy_mem_init},
#endif
{OS_MEM_ALG_DEFAULT, OS_NULL}};
#ifdef OS_USING_HEAP
static os_list_node_t gs_os_heap_resource_list_head = OS_LIST_INIT(gs_os_heap_resource_list_head);
static OS_DEFINE_SPINLOCK(gs_os_heap_resource_list_lock);
/**
***********************************************************************************************************************
* @brief This function initializes heap.
*
* @param[in] heap_cb The ID of heap object.
* @param[in] name The name of heap.
*
* @return The operation result.
* @retval OS_SUCCESS If the operation successful.
* @retval else Error code.
***********************************************************************************************************************
*/
os_heap_id os_heap_init(os_heap_dummy_t *heap_cb, const char *name)
{
os_list_node_t *pos;
os_heap_t *item_heap;
os_heap_t *heap;
os_err_t ret;
heap = OS_TYPE_CONVERT(os_heap_t *, heap_cb);
OS_ASSERT(heap);
ret = OS_SUCCESS;
os_spin_lock(&gs_os_heap_resource_list_lock);
os_list_for_each(pos, &gs_os_heap_resource_list_head)
{
item_heap = os_list_entry(pos, os_heap_t, resource_node);
if (item_heap == heap)
{
os_spin_unlock(&gs_os_heap_resource_list_lock);
OS_KERN_LOG(KERN_ERROR, MEM_TAG, "The heap(addr: %p) already exist", item_heap);
ret = OS_INVAL;
heap = OS_NULL;
break;
}
}
if (OS_SUCCESS == ret)
{
os_list_add_tail(&gs_os_heap_resource_list_head, &heap->resource_node);
os_spin_unlock(&gs_os_heap_resource_list_lock);
if (OS_NULL != name)
{
strncpy(&heap->name[0], name, OS_NAME_MAX);
heap->name[OS_NAME_MAX] = '\0';
}
else
{
heap->name[0] = '\0';
}
heap->h_mem = OS_NULL;
heap->object_inited = OS_KOBJ_INITED;
}
return OS_TYPE_CONVERT(os_heap_id, heap);
}
/**
***********************************************************************************************************************
* @brief This function add memory zone to heap which has been inited, combine multiple memory zone.
*
* @param[in] heap_id The ID of heap object.
* @param[in] start_addr The start address of memory zone.
* @param[in] size The size of this memory zone.
* @param[in] alg The memory algorithm for this memory zone.
*
* @return The operation result.
* @retval OS_SUCCESS If the operation successful.
* @retval else Error code.
***********************************************************************************************************************
*/
os_err_t os_heap_add(os_heap_id heap_id, void *start_addr, os_size_t size, enum os_mem_alg alg)
{
os_size_t start;
struct heap_mem *h_mem;
struct heap_mem *h_mem_new;
os_bool_t mem_inited = OS_FALSE;
os_size_t i;
os_list_node_t *pos;
os_heap_t *item_heap;
os_heap_t *heap;
struct heap_mem *h_mem_temp;
os_size_t h_mem_temp_start;
os_size_t h_mem_temp_end;
os_err_t ret;
heap = OS_TYPE_CONVERT(os_heap_t *, heap_id);
OS_ASSERT(OS_NULL != heap);
OS_ASSERT(OS_KOBJ_INITED == heap->object_inited);
OS_ASSERT(alg <= OS_MEM_ALG_DEFAULT);
if (OS_MEM_ALG_DEFAULT == alg)
{
alg = ((enum os_mem_alg)0);
}
ret = OS_SUCCESS;
start = OS_ALIGN_UP((os_size_t)(char *)start_addr, OS_ALIGN_SIZE);
OS_ASSERT(((os_size_t)(char *)start_addr + size) > start);
size = OS_ALIGN_DOWN((os_size_t)(char *)start_addr + size - start, OS_ALIGN_SIZE);
if (size > sizeof(struct heap_mem))
{
os_spin_lock(&gs_os_heap_resource_list_lock);
/* Search each memheap. */
os_list_for_each(pos, &gs_os_heap_resource_list_head)
{
item_heap = os_list_entry(pos, os_heap_t, resource_node);
/* Every memheap may contains multiple memory. Check each memory. */
h_mem_temp = item_heap->h_mem;
while (OS_NULL != h_mem_temp)
{
h_mem_temp_start = (os_size_t)h_mem_temp;
h_mem_temp_end = (os_size_t)(char *)h_mem_temp->header + h_mem_temp->mem_total;
OS_ASSERT(h_mem_temp_start < h_mem_temp_end);
if (!((start >= h_mem_temp_end) || (h_mem_temp_start >= (start + size))))
{
OS_KERN_LOG(KERN_ERROR, MEM_TAG, "memory is overlaped, please check !");
ret = OS_INVAL;
break;
}
h_mem_temp = h_mem_temp->next;
}
if (OS_SUCCESS != ret)
{
os_spin_unlock(&gs_os_heap_resource_list_lock);
break;
}
}
}
else
{
OS_KERN_LOG(KERN_ERROR, MEM_TAG, "memory is too small !");
ret = OS_NOMEM;
}
if (OS_SUCCESS == ret)
{
h_mem_new = (struct heap_mem *)start;
(void)memset((void *)h_mem_new, 0, sizeof(struct heap_mem));
start += sizeof(struct heap_mem);
size -= sizeof(struct heap_mem);
for (i = 0; i < (sizeof(alg_init_table) / sizeof(struct alg_init_func)); i++)
{
if (alg == alg_init_table[i].mem_alg)
{
alg_init_table[i].mem_init(h_mem_new, (void *)(char *)start, size);
mem_inited = OS_TRUE;
break;
}
}
if (OS_TRUE == mem_inited)
{
if (OS_NULL != heap->h_mem)
{
h_mem = heap->h_mem;
while (OS_NULL != h_mem->next)
{
h_mem = h_mem->next;
}
h_mem->next = h_mem_new;
}
else
{
heap->h_mem = h_mem_new;
}
}
else
{
OS_KERN_LOG(KERN_ERROR, MEM_TAG, "memory algorithm %d not support, please check !", (int32_t)alg);
ret = OS_INVAL;
}
os_spin_unlock(&gs_os_heap_resource_list_lock);
}
return ret;
}
/**
***********************************************************************************************************************
* @brief This function allocates 'size' bytes memory space from heap.
*
* @param[in] heap_id The ID of heap object.
* @param[in] size The size of the requested space in bytes.
*
* @return The pointer to allocated memory or NULL if no free memory was found.
***********************************************************************************************************************
*/
void *os_heap_alloc(os_heap_id heap_id, os_size_t size)
{
os_heap_t *heap;
struct heap_mem *h_mem;
void *ptr;
heap = OS_TYPE_CONVERT(os_heap_t *, heap_id);
OS_ASSERT(heap);
OS_ASSERT(OS_KOBJ_INITED == heap->object_inited);
ptr = OS_NULL;
h_mem = heap->h_mem;
while (h_mem && h_mem->k_alloc)
{
ptr = h_mem->k_alloc(h_mem, size);
if (ptr)
{
break;
}
h_mem = h_mem->next;
}
return ptr;
}
/**
***********************************************************************************************************************
* @brief This function allocates a memory, which address is aligned to the specified align size.
*
* @param[in] heap_id The ID of heap object.
* @param[in] align The alignment size.
* @param[in] size The allocated memory block size.
*
* @return The pointer to allocated memory or NULL if no free memory was found.
***********************************************************************************************************************
*/
void *os_heap_aligned_alloc(os_heap_id heap_id, os_size_t align, os_size_t size)
{
struct heap_mem *h_mem;
void *ptr;
os_heap_t *heap;
heap = OS_TYPE_CONVERT(os_heap_t *, heap_id);
OS_ASSERT(heap);
OS_ASSERT(OS_KOBJ_INITED == heap->object_inited);
ptr = OS_NULL;
h_mem = heap->h_mem;
while (h_mem && h_mem->k_aligned_alloc)
{
ptr = h_mem->k_aligned_alloc(h_mem, align, size);
if (ptr)
{
break;
}
h_mem = h_mem->next;
}
return ptr;
}
/**
***********************************************************************************************************************
* @brief This function changes the size of the memory to 'newsize' bytes.
*
* @param[in] heap_id The ID of heap object.
* @param[in] ptr The pointer to old memory block.
* @param[in] size The size of the requested memory in bytes.
*
* @return The pointer to allocated memory or NULL if no free memory was found.
***********************************************************************************************************************
*/
void *os_heap_realloc(os_heap_id heap_id, void *ptr, os_size_t size)
{
struct heap_mem *h_mem;
struct heap_mem *h_mem_new;
os_size_t oldsize;
void *ptr_new;
os_heap_t *heap;
heap = OS_TYPE_CONVERT(os_heap_t *, heap_id);
OS_ASSERT(heap);
OS_ASSERT(OS_KOBJ_INITED == heap->object_inited);
h_mem = OS_NULL;
ptr_new = OS_NULL;
if (!ptr)
{
ptr_new = os_heap_alloc((os_heap_id)heap, size);
}
else
{
/* Find the original h_mem. */
h_mem = heap->h_mem;
while (h_mem)
{
if ((ptr >= h_mem->header) && (((os_size_t)ptr - (os_size_t)h_mem->header) <= h_mem->mem_total))
{
break;
}
h_mem = h_mem->next;
}
/* Realloc in the original h_mem. */
if (h_mem && h_mem->k_realloc)
{
ptr_new = h_mem->k_realloc(h_mem, ptr, size);
}
OS_ASSERT_EX(h_mem, "unexpected heap or mem addr (invalid addr: %p ?)", ptr);
}
if ((!ptr_new) && h_mem && (h_mem->k_free))
{
/* Alloc in the other h_mem. */
h_mem_new = heap->h_mem;
while (h_mem_new)
{
if ((h_mem_new != h_mem) && (h_mem_new->k_alloc))
{
ptr_new = h_mem_new->k_alloc(h_mem_new, size);
if (ptr_new)
{
oldsize = h_mem->k_ptr_to_size(h_mem, ptr);
memcpy(ptr_new, ptr, oldsize > size ? size : oldsize);
h_mem->k_free(h_mem, ptr);
break;
}
}
h_mem_new = h_mem_new->next;
}
}
return ptr_new;
}
/**
***********************************************************************************************************************
* @brief This function frees the memory space pointed to by ptr, which allocated by a previous
* os_memheap_malloc() or os_heap_realloc() or os_heap_aligned_alloc().
*
* @param[in] heap_id The ID of heap object.
* @param[in] ptr The pointer to memory block.
*
* @return None.
***********************************************************************************************************************
*/
void os_heap_free(os_heap_id heap_id, void *ptr)
{
struct heap_mem *h_mem;
os_heap_t *heap;
heap = OS_TYPE_CONVERT(os_heap_t *, heap_id);
OS_ASSERT(heap);
OS_ASSERT(OS_KOBJ_INITED == heap->object_inited);
OS_ASSERT(ptr);
h_mem = heap->h_mem;
while (h_mem)
{
if ((ptr >= h_mem->header) && ((os_size_t)ptr <= ((os_size_t)h_mem->header + h_mem->mem_total)))
{
if (h_mem->k_free)
{
h_mem->k_free(h_mem, ptr);
}
break;
}
h_mem = h_mem->next;
}
OS_ASSERT_EX(h_mem, "unexpected heap or mem addr (invalid addr: %p ?)", ptr);
}
/**
***********************************************************************************************************************
* @brief This function get heap info.
*
* @param[in] heap_id The ID of heap object.
* @param[in,out] info The heap info, which include mem_total, mem_used, mem_maxused.
*
* @return None.
***********************************************************************************************************************
*/
void os_heap_info(os_heap_id heap_id, os_meminfo_t *info)
{
struct heap_mem *h_mem;
os_heap_t *heap;
heap = OS_TYPE_CONVERT(os_heap_t *, heap_id);
OS_ASSERT(heap);
OS_ASSERT(OS_KOBJ_INITED == heap->object_inited);
OS_ASSERT(info);
(void)memset(info, 0, sizeof(os_meminfo_t));
h_mem = heap->h_mem;
while (h_mem)
{
info->mem_total += h_mem->mem_total;
info->mem_used += h_mem->mem_used;
info->mem_maxused += h_mem->mem_maxused;
h_mem = h_mem->next;
}
}
/**
***********************************************************************************************************************
* @brief This function check whether the heap is correct.
*
* @param[in] heap_id The ID of heap object.
*
* @retval OS_SUCCESS Check successful.
* @retval else Check error.
***********************************************************************************************************************
*/
os_err_t os_heap_check(os_heap_id heap_id)
{
struct heap_mem *h_mem;
os_err_t ret;
os_heap_t *heap;
heap = OS_TYPE_CONVERT(os_heap_t *, heap_id);
OS_ASSERT(heap);
OS_ASSERT(OS_KOBJ_INITED == heap->object_inited);
ret = OS_SUCCESS;
h_mem = heap->h_mem;
while (h_mem)
{
if (h_mem->k_mem_check)
{
ret = h_mem->k_mem_check(h_mem);
if (ret != OS_SUCCESS)
{
break;
}
}
h_mem = h_mem->next;
}
return ret;
}
#ifdef OS_USING_MEM_TRACE
/**
***********************************************************************************************************************
* @brief This function trace task info for every allocated memory.
*
* @param[in] heap_id The ID of heap object.
*
* @retval OS_SUCCESS Trace successful.
* @retval else Trace error.
***********************************************************************************************************************
*/
os_err_t os_heap_trace(os_heap_id heap_id)
{
struct heap_mem *h_mem;
os_err_t ret;
os_heap_t *heap;
heap = OS_TYPE_CONVERT(os_heap_t *, heap_id);
OS_ASSERT(heap);
OS_ASSERT(OS_KOBJ_INITED == heap->object_inited);
ret = OS_SUCCESS;
h_mem = heap->h_mem;
while (h_mem)
{
if (h_mem->k_mem_trace)
{
h_mem->k_mem_trace(h_mem);
if (ret != OS_SUCCESS)
{
break;
}
}
h_mem = h_mem->next;
}
return ret;
}
#endif
#ifdef OS_USING_SHELL
#include <shell.h>
#define RATE_STRING_MAX 7
static void rate_to_string(int32_t rate, char *rate_str)
{
uint32_t integer_part;
uint32_t fractional_part;
/* 1 corresponds to 0.01%, and the maximum value is 10000. */
if ((rate < 0) || (rate > 10000))
{
*rate_str = '\0';
return;
}
integer_part = rate / 100;
fractional_part = rate % 100;
/* 0% */
if ((0 == integer_part) && (0 == fractional_part))
{
os_snprintf(rate_str, RATE_STRING_MAX, "0%% ");
}
/* 100% */
else if (integer_part == 100)
{
os_snprintf(rate_str, RATE_STRING_MAX, "100%% ");
}
else
{
if (integer_part < 10)
{
if (0 == fractional_part)
{
os_snprintf(rate_str, RATE_STRING_MAX, "%d%% ", integer_part);
}
else
{
os_snprintf(rate_str, RATE_STRING_MAX, "%d.%02d%% ", integer_part, fractional_part);
}
}
else
{
if (0 == fractional_part)
{
os_snprintf(rate_str, RATE_STRING_MAX, "%d%% ", integer_part);
}
else
{
os_snprintf(rate_str, RATE_STRING_MAX, "%d.%02d%%", integer_part, fractional_part);
}
}
}
}
static void heap_title_show(void)
{
uint16_t len;
/* clang-format off */
os_kprintf("[Tips]: \r\n"
"Total: The total size of a memory heap,described in bytes.\r\n");
os_kprintf("Used: The amount of memory currently in use,described in bytes.\r\n");
os_kprintf("Used rate:The percentage of memory currently being used.\r\n");
os_kprintf("Max Used: Maximum memory used in history,described in bytes.\r\n");
os_kprintf("Max rate: Maximum memory percentage used in history.\r\n");
os_kprintf("Range: All address space ranges of the memory heap.\r\n"
"\r\n");
/* clang-format on */
os_kprintf("%-*s Total Used Used rate Max Used Max rate Range\r\n", OS_NAME_MAX, "Name");
len = OS_NAME_MAX;
while (len--)
{
os_kprintf("-");
}
os_kprintf(" ---------- ---------- ---------- ---------- ---------- -----\r\n");
}
os_err_t os_heap_show(os_heap_t *heap)
{
os_meminfo_t info;
struct heap_mem *h_mem;
uint64_t rate;
char rate_str[2][RATE_STRING_MAX];
os_heap_info((os_heap_id)heap, &info);
rate = (uint64_t)info.mem_used * 10000 / info.mem_total;
rate_to_string(rate, rate_str[0]);
rate = (uint64_t)info.mem_maxused * 10000 / info.mem_total;
rate_to_string(rate, rate_str[1]);
os_kprintf("%-*s %-10lu %-10lu %6s %-10lu %6s ",
OS_NAME_MAX,
(heap->name[0] != '\0') ? heap->name : "-",
info.mem_total,
info.mem_used,
rate_str[0],
info.mem_maxused,
rate_str[1]);
h_mem = heap->h_mem;
while (h_mem)
{
os_kprintf("[%p~%p] ", h_mem->header, (void *)((os_size_t)h_mem->header + (os_size_t)h_mem->mem_total));
h_mem = h_mem->next;
}
os_kprintf("\r\n");
return OS_SUCCESS;
}
os_err_t sh_heap_show(int32_t argc, char **argv)
{
os_list_node_t *pos;
os_heap_t *item_heap;
OS_UNREFERENCE(argc);
OS_UNREFERENCE(argv);
heap_title_show();
os_spin_lock(&gs_os_heap_resource_list_lock);
os_list_for_each(pos, &gs_os_heap_resource_list_head)
{
item_heap = os_list_entry(pos, os_heap_t, resource_node);
os_heap_show(item_heap);
}
os_spin_unlock(&gs_os_heap_resource_list_lock);
return OS_SUCCESS;
}
SH_CMD_EXPORT(show_heap, sh_heap_show, "show memheap information");
#endif
#endif /* end of OS_USING_HEAP */
#ifdef OS_USING_HEAP
static os_heap_id gs_default_heap;
OS_HEAP_DEFINE(gs_default_heap_control_block);
/**
***********************************************************************************************************************
* @brief This function initializes the default_heap.
*
* @param[in] None.
*
* @return None.
***********************************************************************************************************************
*/
void os_default_heap_init(void)
{
(void)memset(&gs_default_heap_control_block, 0, sizeof(os_heap_dummy_t));
gs_default_heap = os_heap_init(&gs_default_heap_control_block, "DEFAULT_HEAP");
if (!gs_default_heap)
{
OS_KERN_LOG(KERN_ERROR, MEM_TAG, "default memory heap init failed!");
}
}
/**
***********************************************************************************************************************
* @brief This function add memory zone to the default_heap, combine multiple memory zone together.
*
* @param[in] start_addr The start address of memory.
* @param[in] size The size of this memory zone.
* @param[in] alg The memory algorithm for this memory zone.
*
* @return The operation result.
* @retval OS_SUCCESS If the operation successful.
* @retval else Error code.
***********************************************************************************************************************
*/
os_err_t os_default_heap_add(void *start_addr, os_size_t size, enum os_mem_alg alg)
{
return os_heap_add(gs_default_heap, start_addr, size, alg);
}
/**
***********************************************************************************************************************
* @brief This function allocates 'size' bytes from default_heap, returns pointer of the allocated memory.
*
* @param[in] size The size of the requested block in bytes.
*
* @return The pointer to allocated memory or OS_NULL if no free memory was found.
***********************************************************************************************************************
*/
void *os_malloc(os_size_t size)
{
return os_heap_alloc(gs_default_heap, size);
}
/**
***********************************************************************************************************************
* @brief This function allocates a memory block from default_heap, which address is aligned to the
* specified alignment size.
*
* @param[in] align The alignment size.
* @param[in] size The allocated memory block size.
*
* @return The allocated memory pointer.
* @retval OS_NULL Allocated memory block failed.
* @retval else Allocated memory block successfull.
***********************************************************************************************************************
*/
void *os_aligned_malloc(os_size_t align, os_size_t size)
{
return os_heap_aligned_alloc(gs_default_heap, align, size);
}
/**
***********************************************************************************************************************
* @brief This function changes the size of the memory block pointed to by 'ptr' to 'newsize' bytes. If size
* is equal to 0, it works in the same way as os_free(). If 'ptr' is OS_NULL, it works in the same way
* as os_malloc().
*
* @param[in] ptr The pointer of memory block to change.
* @param[in] size The size of new memory block.
*
* @return The pointer to newly allocated memory or NULL.
***********************************************************************************************************************
*/
void *os_realloc(void *ptr, os_size_t size)
{
return os_heap_realloc(gs_default_heap, ptr, size);
}
/**
***********************************************************************************************************************
* @brief This function allocates memory for an array of 'count' elements of 'size' bytes each and returns a
* pointer to the allocated memory. The memory is set to zero.
*
* @param[in] count Number of array to allocate.
* @param[in] size Size of each element to allocate.
*
* @return The pointer to allocated memory or OS_NULL if no free memory was found.
***********************************************************************************************************************
*/
void *os_calloc(os_size_t count, os_size_t size)
{
void *ptr;
ptr = os_heap_alloc(gs_default_heap, count * size);
if (ptr)
{
(void)memset(ptr, 0, count * size);
}
return ptr;
}
/**
***********************************************************************************************************************
* @brief This function frees the memory space pointed to by 'ptr', which allocated by os_malloc(), or
* os_realloc() or os_calloc() or os_aligned_malloc().
*
* @param[in] ptr The pointer to memory space.
*
* @return None.
***********************************************************************************************************************
*/
void os_free(void *ptr)
{
os_heap_free(gs_default_heap, ptr);
}
/**
***********************************************************************************************************************
* @brief This function get memory info for default_heap.
*
* @param[in,out] info The default_heap info, which include mem_total, mem_used, mem_maxused.
*
* @return None.
***********************************************************************************************************************
*/
void os_default_heap_info(os_meminfo_t *info)
{
OS_ASSERT(info);
os_heap_info(gs_default_heap, info);
}
/**
***********************************************************************************************************************
* @brief This function check whether the default_heap is correct.
*
* @param[in] NONE.
*
* @retval OS_SUCCESS Check successful.
* @retval else Check error.
***********************************************************************************************************************
*/
os_err_t os_default_heap_check(void)
{
return os_heap_check(gs_default_heap);
}
#ifdef OS_USING_MEM_TRACE
/**
***********************************************************************************************************************
* @brief This fuction trace task info for every allocated memory from default_heap.
*
* @param[in] NONE.
*
* @retval OS_SUCCESS Trace successful.
* @retval else Trace error.
***********************************************************************************************************************
*/
os_err_t os_default_heap_trace(void)
{
return os_heap_trace(gs_default_heap);
}
#endif
#ifdef OS_USING_SHELL
#include <shell.h>
os_err_t sh_memshow(int32_t argc, char **argv)
{
os_heap_t *heap;
OS_UNREFERENCE(argc);
OS_UNREFERENCE(argv);
heap = OS_TYPE_CONVERT(os_heap_t *, gs_default_heap);
heap_title_show();
os_heap_show(heap);
return OS_SUCCESS;
}
SH_CMD_EXPORT(show_mem, sh_memshow, "show memory usage information");
os_err_t sh_memcheck(int32_t argc, char **argv)
{
OS_UNREFERENCE(argc);
OS_UNREFERENCE(argv);
return os_default_heap_check();
}
SH_CMD_EXPORT(check_mem, sh_memcheck, "check memory data");
#ifdef OS_USING_MEM_TRACE
os_err_t sh_memtrace(int32_t argc, char **argv)
{
OS_UNREFERENCE(argc);
OS_UNREFERENCE(argv);
return os_default_heap_trace();
}
SH_CMD_EXPORT(trace_mem, sh_memtrace, "trace memory used by task");
#endif /* end of OS_USING_MEM_TRACE */
#endif /* end of OS_USING_SHELL */
#endif /* end of OS_USING_HEAP */