From 1d66d5c297cde6398d2a598d0f34035c356ea412 Mon Sep 17 00:00:00 2001 From: ligd Date: Thu, 18 Feb 2021 11:19:32 +0800 Subject: [PATCH] debug tools: add heap & stack check in idle thread N/A Change-Id: Iba6f5cdffb1336697096c71fca86c9ece584225f Signed-off-by: ligd --- include/nuttx/mm/mm.h | 25 ++++++ mm/kmm_heap/Make.defs | 4 + mm/kmm_heap/kmm_checkcorruption.c | 48 +++++++++++ mm/mm_heap/Make.defs | 5 ++ mm/mm_heap/mm_checkcorruption.c | 127 ++++++++++++++++++++++++++++++ mm/umm_heap/Make.defs | 4 + mm/umm_heap/umm_checkcorruption.c | 46 +++++++++++ sched/init/nx_start.c | 11 +++ 8 files changed, 270 insertions(+) create mode 100644 mm/kmm_heap/kmm_checkcorruption.c create mode 100644 mm/mm_heap/mm_checkcorruption.c create mode 100644 mm/umm_heap/umm_checkcorruption.c diff --git a/include/nuttx/mm/mm.h b/include/nuttx/mm/mm.h index f42c48a7ee..995920ec29 100644 --- a/include/nuttx/mm/mm.h +++ b/include/nuttx/mm/mm.h @@ -487,6 +487,31 @@ int mm_mallinfo(FAR struct mm_heap_s *heap, FAR struct mallinfo *info); struct mallinfo kmm_mallinfo(void); #endif +#ifdef CONFIG_DEBUG_MM +/* Functions contained in mm_checkcorruption.c ******************************/ + +void mm_checkcorruption(FAR struct mm_heap_s *heap); + +/* Functions contained in umm_checkcorruption.c *****************************/ + +FAR void umm_checkcorruption(void); + +/* Functions contained in kmm_checkcorruption.c *****************************/ + +#ifdef CONFIG_MM_KERNEL_HEAP +FAR void kmm_checkcorruption(void); +#else +#define kmm_checkcorruption() umm_checkcorruption() +#endif + +#else /* CONFIG_DEBUG_MM */ + +#define mm_checkcorruption(h) +#define umm_checkcorruption() +#define kmm_checkcorruption() + +#endif /* CONFIG_DEBUG_MM */ + /* Functions contained in mm_shrinkchunk.c **********************************/ void mm_shrinkchunk(FAR struct mm_heap_s *heap, diff --git a/mm/kmm_heap/Make.defs b/mm/kmm_heap/Make.defs index 8aa0169246..68d91861b5 100644 --- a/mm/kmm_heap/Make.defs +++ b/mm/kmm_heap/Make.defs @@ -30,6 +30,10 @@ ifeq ($(CONFIG_BUILD_KERNEL),y) CSRCS += kmm_sbrk.c endif +ifeq ($(CONFIG_DEBUG_MM),y) +CSRCS += kmm_checkcorruption.c +endif + # Add the kernel heap directory to the build DEPPATH += --dep-path kmm_heap diff --git a/mm/kmm_heap/kmm_checkcorruption.c b/mm/kmm_heap/kmm_checkcorruption.c new file mode 100644 index 0000000000..0f0e4ad038 --- /dev/null +++ b/mm/kmm_heap/kmm_checkcorruption.c @@ -0,0 +1,48 @@ +/**************************************************************************** + * mm/kmm_heap/kmm_checkcorruption.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#ifdef CONFIG_MM_KERNEL_HEAP + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: kmm_checkcorruption + * + * Description: + * kmm_checkcorruption is used to check whether memory heap is normal. + * + ****************************************************************************/ + +void kmm_checkcorruption(void) +{ + mm_checkcorruption(&g_kmmheap); +} + +#endif /* CONFIG_MM_KERNEL_HEAP */ diff --git a/mm/mm_heap/Make.defs b/mm/mm_heap/Make.defs index 600dda01e9..c681fa94a2 100644 --- a/mm/mm_heap/Make.defs +++ b/mm/mm_heap/Make.defs @@ -29,6 +29,11 @@ ifeq ($(CONFIG_BUILD_KERNEL),y) CSRCS += mm_sbrk.c endif +ifeq ($(CONFIG_DEBUG_MM),y) +CSRCS += mm_checkcorruption.c +endif + + # Add the core heap directory to the build DEPPATH += --dep-path mm_heap diff --git a/mm/mm_heap/mm_checkcorruption.c b/mm/mm_heap/mm_checkcorruption.c new file mode 100644 index 0000000000..c4ae135d0e --- /dev/null +++ b/mm/mm_heap/mm_checkcorruption.c @@ -0,0 +1,127 @@ +/**************************************************************************** + * mm/mm_heap/mm_checkcorruption.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mm_checkcorruption + * + * Description: + * mm_checkcorruption is used to check whether memory heap is normal. + * + ****************************************************************************/ + +void mm_checkcorruption(FAR struct mm_heap_s *heap) +{ + FAR struct mm_allocnode_s *node; + FAR struct mm_allocnode_s *prev; +#if CONFIG_MM_REGIONS > 1 + int region; +#else +# define region 0 +#endif + + /* Visit each region */ + +#if CONFIG_MM_REGIONS > 1 + for (region = 0; region < heap->mm_nregions; region++) +#endif + { + irqstate_t flags = 0; + + prev = NULL; + + /* Visit each node in the region + * Retake the semaphore for each region to reduce latencies + */ + + if (up_interrupt_context() || sched_idletask()) + { + if (heap->mm_counts_held) + { +#if CONFIG_MM_REGIONS > 1 + continue; +#else + return; +#endif + } + + flags = enter_critical_section(); + } + else + { + mm_takesemaphore(heap); + } + + for (node = heap->mm_heapstart[region]; + node < heap->mm_heapend[region]; + node = (FAR struct mm_allocnode_s *) + ((FAR char *)node + node->size)) + { + if ((node->preceding & MM_ALLOC_BIT) != 0) + { + assert(node->size >= SIZEOF_MM_ALLOCNODE); + } + else + { + FAR struct mm_freenode_s *fnode = (FAR void *)node; + + assert(node->size >= SIZEOF_MM_FREENODE); + assert(fnode->blink->flink == fnode); + assert(fnode->blink->size <= fnode->size); + assert(fnode->flink == NULL || + fnode->flink->blink == fnode); + assert(fnode->flink == NULL || + fnode->flink->size == 0 || + fnode->flink->size >= fnode->size); + } + + assert(prev == NULL || + prev->size == (node->preceding & ~MM_ALLOC_BIT)); + prev = node; + } + + assert(node == heap->mm_heapend[region]); + + if (up_interrupt_context() || sched_idletask()) + { + leave_critical_section(flags); + } + else + { + mm_givesemaphore(heap); + } + } +} diff --git a/mm/umm_heap/Make.defs b/mm/umm_heap/Make.defs index fc9d6d52f0..ceb0607900 100644 --- a/mm/umm_heap/Make.defs +++ b/mm/umm_heap/Make.defs @@ -29,6 +29,10 @@ ifeq ($(CONFIG_BUILD_KERNEL),y) CSRCS += umm_sbrk.c endif +ifeq ($(CONFIG_DEBUG_MM),y) +CSRCS += umm_checkcorruption.c +endif + # Add the user heap directory to the build DEPPATH += --dep-path umm_heap diff --git a/mm/umm_heap/umm_checkcorruption.c b/mm/umm_heap/umm_checkcorruption.c new file mode 100644 index 0000000000..3f4ad05bae --- /dev/null +++ b/mm/umm_heap/umm_checkcorruption.c @@ -0,0 +1,46 @@ +/**************************************************************************** + * mm/umm_heap/umm_checkcorruption.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "umm_heap/umm_heap.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: umm_checkcorruption + * + * Description: + * umm_checkcorruption is used to check whether memory heap is normal. + * + ****************************************************************************/ + +void umm_checkcorruption(void) +{ + mm_checkcorruption(USR_HEAP); +} diff --git a/sched/init/nx_start.c b/sched/init/nx_start.c index 7c0e6bbb08..067d9db952 100644 --- a/sched/init/nx_start.c +++ b/sched/init/nx_start.c @@ -798,6 +798,17 @@ void nx_start(void) sinfo("CPU0: Beginning Idle Loop\n"); for (; ; ) { + /* Check heap & stack in idle thread */ + + kmm_checkcorruption(); + +#if defined(CONFIG_STACK_COLORATION) && defined(CONFIG_DEBUG_MM) + for (i = 0; i < CONFIG_MAX_TASKS && g_pidhash[i].tcb; i++) + { + assert(up_check_tcbstack_remain(g_pidhash[i].tcb) > 0); + } +#endif + /* Perform any processor-specific idle state operations */ up_idle();