aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--os/kernel/src/chdynamic.c13
-rw-r--r--os/kernel/src/chthreads.c5
-rw-r--r--readme.txt2
-rw-r--r--test/testdyn.c37
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 = {