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;
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

View File

@ -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);
}

View File

@ -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

View File

@ -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 = {