Fixed bug 3116888.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2425 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
gdisirio 2010-11-23 20:26:17 +00:00
parent a5bdf86e5b
commit d973c3f25a
4 changed files with 33 additions and 24 deletions

View File

@ -71,17 +71,24 @@ void chThdRelease(Thread *tp) {
refs = --tp->p_refs; refs = --tp->p_refs;
chSysUnlock(); chSysUnlock();
/* If the references counter reaches zero then the memory can be returned /* If the references counter reaches zero and the thread is in its
to the proper allocator. Of course static threads are not affected.*/ terminated state then the memory can be returned to the proper
if (refs == 0) { 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) { switch (tp->p_flags & THD_MEM_MODE_MASK) {
#if CH_USE_HEAP #if CH_USE_HEAP
case THD_MEM_MODE_HEAP: case THD_MEM_MODE_HEAP:
#if CH_USE_REGISTRY
REG_REMOVE(tp);
#endif
chHeapFree(tp); chHeapFree(tp);
break; break;
#endif #endif
#if CH_USE_MEMPOOLS #if CH_USE_MEMPOOLS
case THD_MEM_MODE_MEMPOOL: case THD_MEM_MODE_MEMPOOL:
#if CH_USE_REGISTRY
REG_REMOVE(tp);
#endif
chPoolFree(tp->p_mpool, tp); chPoolFree(tp->p_mpool, tp);
break; break;
#endif #endif

View File

@ -342,7 +342,10 @@ void chThdExit(msg_t msg) {
chSchReadyI(list_remove(&tp->p_waiting)); chSchReadyI(list_remove(&tp->p_waiting));
#endif #endif
#if CH_USE_REGISTRY #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 #endif
chSchGoSleepS(THD_STATE_FINAL); chSchGoSleepS(THD_STATE_FINAL);
} }

View File

@ -65,6 +65,8 @@
***************************************************************************** *****************************************************************************
*** 2.1.4 *** *** 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 - FIX: Fixed failure in STM32 ADC driver when a linear buffer mode is used
(bug 3114696). (bug 3114696).
- FIX: Fixed PWM channels going to ACTIVE state when the pulse width is - FIX: Fixed PWM channels going to ACTIVE state when the pulse width is

View File

@ -190,16 +190,16 @@ ROMCONST struct testcase testdyn2 = {
* coverage. * coverage.
*/ */
static unsigned regscan(void) { static bool_t regfind(Thread *tp) {
Thread *tp; Thread *ftp;
unsigned i = 0; bool_t found = FALSE;
tp = chRegFirstThread(); ftp = chRegFirstThread();
do { do {
i++; found |= ftp == tp;
tp = chRegNextThread(tp); ftp = chRegNextThread(ftp);
} while (tp != NULL); } while (ftp != NULL);
return i; return found;
} }
static void dyn3_setup(void) { static void dyn3_setup(void) {
@ -208,15 +208,9 @@ static void dyn3_setup(void) {
} }
static void dyn3_execute(void) { static void dyn3_execute(void) {
unsigned n1, n2, n3;
Thread *tp; Thread *tp;
tprio_t prio = chThdGetPriority(); 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.*/ /* Testing references increase/decrease and final detach.*/
tp = chThdCreateFromHeap(&heap1, WA_SIZE, prio-1, thread, "A"); tp = chThdCreateFromHeap(&heap1, WA_SIZE, prio-1, thread, "A");
test_assert(1, tp->p_refs == 1, "wrong initial reference counter"); 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"); test_assert(3, tp->p_refs == 1, "references decrease failure");
/* Verify the new threads count.*/ /* Verify the new threads count.*/
n2 = regscan(); test_assert(4, regfind(tp), "thread missing from registry");
test_assert(4, n1 == n2 - 1, "unexpected threads count"); test_assert(5, regfind(tp), "thread disappeared");
/* Detach and let the thread execute and terminate.*/ /* Detach and let the thread execute and terminate.*/
chThdRelease(tp); 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. */ 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.*/ /* Clearing the zombie by scanning the registry.*/
n3 = regscan(); test_assert(11, regfind(tp), "thread disappeared");
test_assert(7, n1 == n3, "unexpected threads count"); test_assert(12, !regfind(tp), "thread still in registry");
} }
ROMCONST struct testcase testdyn3 = { ROMCONST struct testcase testdyn3 = {