From d973c3f25a6ab56e12b9f858b0692ec4297d84c9 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Tue, 23 Nov 2010 20:26:17 +0000 Subject: Fixed bug 3116888. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2425 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/kernel/src/chdynamic.c | 13 ++++++++++--- os/kernel/src/chthreads.c | 5 ++++- readme.txt | 2 ++ test/testdyn.c | 37 +++++++++++++++++-------------------- 4 files changed, 33 insertions(+), 24 deletions(-) diff --git a/os/kernel/src/chdynamic.c b/os/kernel/src/chdynamic.c index 06e5bd00a..5f1fc3401 100644 --- a/os/kernel/src/chdynamic.c +++ b/os/kernel/src/chdynamic.c @@ -71,17 +71,24 @@ void chThdRelease(Thread *tp) { refs = --tp->p_refs; chSysUnlock(); - /* If the references counter reaches zero then the memory can be returned - to the proper allocator. Of course static threads are not affected.*/ - if (refs == 0) { + /* If the references counter reaches zero and the thread is in its + terminated state then the memory can be returned to the proper + allocator. Of course static threads are not affected.*/ + if ((refs == 0) && (tp->p_state == THD_STATE_FINAL)) { switch (tp->p_flags & THD_MEM_MODE_MASK) { #if CH_USE_HEAP case THD_MEM_MODE_HEAP: +#if CH_USE_REGISTRY + REG_REMOVE(tp); +#endif chHeapFree(tp); break; #endif #if CH_USE_MEMPOOLS case THD_MEM_MODE_MEMPOOL: +#if CH_USE_REGISTRY + REG_REMOVE(tp); +#endif chPoolFree(tp->p_mpool, tp); break; #endif diff --git a/os/kernel/src/chthreads.c b/os/kernel/src/chthreads.c index 4e8ae1c21..ced8a77e0 100644 --- a/os/kernel/src/chthreads.c +++ b/os/kernel/src/chthreads.c @@ -342,7 +342,10 @@ void chThdExit(msg_t msg) { chSchReadyI(list_remove(&tp->p_waiting)); #endif #if CH_USE_REGISTRY - REG_REMOVE(tp); + /* Static threads are immediately removed from the registry because + there is no memory to recover.*/ + if ((tp->p_flags & THD_MEM_MODE_MASK) == THD_MEM_MODE_STATIC) + REG_REMOVE(tp); #endif chSchGoSleepS(THD_STATE_FINAL); } diff --git a/readme.txt b/readme.txt index bf9901e1e..c708996d0 100644 --- a/readme.txt +++ b/readme.txt @@ -65,6 +65,8 @@ ***************************************************************************** *** 2.1.4 *** +- FIX: Fixed failed memory recovery by registry scan, improved the related + test case (bug 3116888)(backported to 2.0.8). - FIX: Fixed failure in STM32 ADC driver when a linear buffer mode is used (bug 3114696). - FIX: Fixed PWM channels going to ACTIVE state when the pulse width is diff --git a/test/testdyn.c b/test/testdyn.c index 69a1c3312..2035224a1 100644 --- a/test/testdyn.c +++ b/test/testdyn.c @@ -190,16 +190,16 @@ ROMCONST struct testcase testdyn2 = { * coverage. */ -static unsigned regscan(void) { - Thread *tp; - unsigned i = 0; +static bool_t regfind(Thread *tp) { + Thread *ftp; + bool_t found = FALSE; - tp = chRegFirstThread(); + ftp = chRegFirstThread(); do { - i++; - tp = chRegNextThread(tp); - } while (tp != NULL); - return i; + found |= ftp == tp; + ftp = chRegNextThread(ftp); + } while (ftp != NULL); + return found; } static void dyn3_setup(void) { @@ -208,15 +208,9 @@ static void dyn3_setup(void) { } static void dyn3_execute(void) { - unsigned n1, n2, n3; Thread *tp; tprio_t prio = chThdGetPriority(); - /* Current number of threads in the system, two times just in case some - external detached thread terminated.*/ - (void)regscan(); - n1 = regscan(); - /* Testing references increase/decrease and final detach.*/ tp = chThdCreateFromHeap(&heap1, WA_SIZE, prio-1, thread, "A"); test_assert(1, tp->p_refs == 1, "wrong initial reference counter"); @@ -226,18 +220,21 @@ static void dyn3_execute(void) { test_assert(3, tp->p_refs == 1, "references decrease failure"); /* Verify the new threads count.*/ - n2 = regscan(); - test_assert(4, n1 == n2 - 1, "unexpected threads count"); + test_assert(4, regfind(tp), "thread missing from registry"); + test_assert(5, regfind(tp), "thread disappeared"); /* Detach and let the thread execute and terminate.*/ chThdRelease(tp); - test_assert(5, tp->p_refs == 0, "detach failure"); + test_assert(6, tp->p_refs == 0, "detach failure"); + test_assert(7, tp->p_state == THD_STATE_READY, "invalid state"); + test_assert(8, regfind(tp), "thread disappeared"); + test_assert(9, regfind(tp), "thread disappeared"); chThdSleepMilliseconds(50); /* The thread just terminates. */ - test_assert(6, tp->p_state == THD_STATE_FINAL, "invalid state"); + test_assert(10, tp->p_state == THD_STATE_FINAL, "invalid state"); /* Clearing the zombie by scanning the registry.*/ - n3 = regscan(); - test_assert(7, n1 == n3, "unexpected threads count"); + test_assert(11, regfind(tp), "thread disappeared"); + test_assert(12, !regfind(tp), "thread still in registry"); } ROMCONST struct testcase testdyn3 = { -- cgit v1.2.3