diff --git a/sched/sched/sched_releasetcb.c b/sched/sched/sched_releasetcb.c index ea44600167..1daa9d24bc 100644 --- a/sched/sched/sched_releasetcb.c +++ b/sched/sched/sched_releasetcb.c @@ -144,7 +144,22 @@ int sched_releasetcb(FAR struct tcb_s *tcb, uint8_t ttype) if (tcb->stack_alloc_ptr) { - up_release_stack(tcb, ttype); +#ifdef CONFIG_BUILD_KERNEL + /* If the exiting thread is not a kernel thread, then it has an + * address environment. Don't bother to release the stack memory + * in this case... There is no point since the memory lies in the + * user memory region that will be destroyed anyway (and the + * address environment has probably already been destroyed at + * this point.. so we would crash if we even tried it). But if + * this is a privileged group, when we still have to release the + * memory using the kernel allocator. + */ + + if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_KERNEL) +#endif + { + up_release_stack(tcb, ttype); + } } #ifdef CONFIG_PIC @@ -169,17 +184,18 @@ int sched_releasetcb(FAR struct tcb_s *tcb, uint8_t ttype) (void)up_addrenv_kstackfree(tcb); #endif +#ifdef CONFIG_ARCH_ADDRENV /* Release this thread's reference to the address environment */ -#ifdef CONFIG_ARCH_ADDRENV ret = up_addrenv_detach(tcb->group, tcb); #endif +#ifdef HAVE_TASK_GROUP /* Leave the group (if we did not already leave in task_exithook.c) */ -#ifdef HAVE_TASK_GROUP group_leave(tcb); #endif + /* And, finally, release the TCB itself */ sched_kfree(tcb); diff --git a/sched/task/task_exithook.c b/sched/task/task_exithook.c index cf7c8c8cdb..585b897d49 100644 --- a/sched/task/task_exithook.c +++ b/sched/task/task_exithook.c @@ -613,6 +613,7 @@ void task_exithook(FAR struct tcb_s *tcb, int status, bool nonblocking) return; } +#if defined(CONFIG_SCHED_ATEXIT) || defined(CONFIG_SCHED_ONEXIT) /* If exit function(s) were registered, call them now before we do any un- * initialization. * @@ -628,7 +629,6 @@ void task_exithook(FAR struct tcb_s *tcb, int status, bool nonblocking) * the exit functions *not* be called. */ -#if defined(CONFIG_SCHED_ATEXIT) || defined(CONFIG_SCHED_ONEXIT) if (!nonblocking) { task_atexit(tcb); @@ -669,17 +669,17 @@ void task_exithook(FAR struct tcb_s *tcb, int status, bool nonblocking) task_flushstreams(tcb); } +#ifdef HAVE_TASK_GROUP /* Leave the task group. Perhaps discarding any un-reaped child * status (no zombies here!) */ -#ifdef HAVE_TASK_GROUP group_leave(tcb); #endif +#ifndef CONFIG_DISABLE_SIGNALS /* Deallocate anything left in the TCB's queues */ -#ifndef CONFIG_DISABLE_SIGNALS sig_cleanup(tcb); /* Deallocate Signal lists */ #endif