From 5713d85df06b9160421386ef0631aef1322f30b6 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Fri, 27 Jan 2023 10:28:19 +0200 Subject: [PATCH] group/group_addrenv: Move address environment from group -> tcb Detach the address environment handling from the group structure to the tcb. This is preparation to fix rare cases where the system (MMU) is left without a valid page directory, e.g. when a process exits. --- arch/arm/include/arch.h | 1 - arch/arm/src/armv7-a/arm_addrenv.c | 23 +-- arch/arm/src/armv7-a/arm_addrenv_shm.c | 18 +- arch/arm/src/armv7-a/arm_doirq.c | 4 +- arch/arm/src/armv7-a/arm_pgalloc.c | 12 +- arch/arm/src/armv7-a/arm_syscall.c | 4 +- arch/arm/src/armv7-r/arm_doirq.c | 1 - arch/arm/src/common/arm_checkstack.c | 2 +- arch/risc-v/src/common/riscv_addrenv.c | 11 +- arch/risc-v/src/common/riscv_addrenv_shm.c | 38 ++--- arch/risc-v/src/common/riscv_checkstack.c | 2 +- arch/risc-v/src/common/riscv_doirq.c | 4 +- arch/risc-v/src/common/riscv_pgalloc.c | 22 ++- .../common/supervisor/riscv_perform_syscall.c | 5 +- arch/z80/src/common/z80_doirq.c | 4 +- arch/z80/src/common/z80_exit.c | 3 +- arch/z80/src/common/z80_switchcontext.c | 4 +- arch/z80/src/z180/z180_mmu.c | 7 +- binfmt/binfmt_execmodule.c | 10 +- include/nuttx/addrenv.h | 91 +++++++++++ include/nuttx/arch.h | 17 +- include/nuttx/sched.h | 22 +-- sched/Makefile | 1 + sched/addrenv/Make.defs | 28 ++++ .../group_addrenv.c => addrenv/addrenv.c} | 154 +++++++++++++++--- sched/group/Make.defs | 4 - sched/group/group.h | 21 +-- sched/group/group_create.c | 6 +- sched/group/group_find.c | 2 +- sched/group/group_leave.c | 24 +-- sched/misc/assert.c | 4 +- sched/pthread/pthread_create.c | 2 +- sched/sched/sched_releasetcb.c | 6 +- sched/task/task_init.c | 17 +- 34 files changed, 369 insertions(+), 205 deletions(-) create mode 100644 sched/addrenv/Make.defs rename sched/{group/group_addrenv.c => addrenv/addrenv.c} (52%) diff --git a/arch/arm/include/arch.h b/arch/arm/include/arch.h index 12d6160461..84f80d2303 100644 --- a/arch/arm/include/arch.h +++ b/arch/arm/include/arch.h @@ -33,7 +33,6 @@ #ifndef __ASSEMBLY__ # include # include -# include #endif /**************************************************************************** diff --git a/arch/arm/src/armv7-a/arm_addrenv.c b/arch/arm/src/armv7-a/arm_addrenv.c index 355e6ca29c..1edadbad50 100644 --- a/arch/arm/src/armv7-a/arm_addrenv.c +++ b/arch/arm/src/armv7-a/arm_addrenv.c @@ -98,8 +98,6 @@ #include #include -#include - #include #include #include @@ -778,22 +776,18 @@ int up_addrenv_clone(const arch_addrenv_t *src, * is created that needs to share the address environment of its task * group. * - * NOTE: In some platforms, nothing will need to be done in this case. - * Simply being a member of the group that has the address environment - * may be sufficient. - * * Input Parameters: - * group - The task group to which the new thread belongs. - * tcb - The TCB of the thread needing the address environment. + * ptcb - The tcb of the parent task. + * tcb - The tcb of the thread needing the address environment. * * Returned Value: * Zero (OK) on success; a negated errno value on failure. * ****************************************************************************/ -int up_addrenv_attach(struct task_group_s *group, struct tcb_s *tcb) +int up_addrenv_attach(struct tcb_s *ptcb, struct tcb_s *tcb) { - binfo("group=%p tcb=%p\n", group, tcb); + binfo("parent=%p tcb=%p\n", ptcb, tcb); /* Nothing needs to be done in this implementation */ @@ -810,12 +804,7 @@ int up_addrenv_attach(struct task_group_s *group, struct tcb_s *tcb) * task group is itself destroyed. Any resources unique to this thread * may be destroyed now. * - * NOTE: In some platforms, nothing will need to be done in this case. - * Simply being a member of the group that has the address environment - * may be sufficient. - * * Input Parameters: - * group - The group to which the thread belonged. * tcb - The TCB of the task or thread whose the address environment will * be released. * @@ -824,9 +813,9 @@ int up_addrenv_attach(struct task_group_s *group, struct tcb_s *tcb) * ****************************************************************************/ -int up_addrenv_detach(struct task_group_s *group, struct tcb_s *tcb) +int up_addrenv_detach(struct tcb_s *tcb) { - binfo("group=%p tcb=%p\n", group, tcb); + binfo("tcb=%p\n", tcb); /* Nothing needs to be done in this implementation */ diff --git a/arch/arm/src/armv7-a/arm_addrenv_shm.c b/arch/arm/src/armv7-a/arm_addrenv_shm.c index 884c0e3224..fdbfa8cf2e 100644 --- a/arch/arm/src/armv7-a/arm_addrenv_shm.c +++ b/arch/arm/src/armv7-a/arm_addrenv_shm.c @@ -66,7 +66,7 @@ int up_shmat(uintptr_t *pages, unsigned int npages, uintptr_t vaddr) { struct tcb_s *tcb = nxsched_self(); - struct task_group_s *group; + struct arch_addrenv_s *addrenv; uintptr_t *l1entry; uint32_t *l2table; irqstate_t flags; @@ -79,11 +79,11 @@ int up_shmat(uintptr_t *pages, unsigned int npages, uintptr_t vaddr) /* Sanity checks */ - DEBUGASSERT(pages && npages > 0 && tcb && tcb->group); + DEBUGASSERT(pages && npages > 0 && tcb && tcb->addrenv_own); DEBUGASSERT(vaddr >= CONFIG_ARCH_SHM_VBASE && vaddr < ARCH_SHM_VEND); DEBUGASSERT(MM_ISALIGNED(vaddr)); - group = tcb->group; + addrenv = &tcb->addrenv_own->addrenv; /* Loop until all pages have been mapped into the caller's address space. */ @@ -97,7 +97,7 @@ int up_shmat(uintptr_t *pages, unsigned int npages, uintptr_t vaddr) * address. */ - l1entry = group->tg_addrenv.shm[shmndx]; + l1entry = addrenv->shm[shmndx]; if (l1entry == NULL) { /* No.. Allocate one physical page for the L2 page table */ @@ -115,7 +115,7 @@ int up_shmat(uintptr_t *pages, unsigned int npages, uintptr_t vaddr) */ flags = enter_critical_section(); - group->tg_addrenv.shm[shmndx] = (uintptr_t *)paddr; + addrenv->shm[shmndx] = (uintptr_t *)paddr; /* Get the virtual address corresponding to the physical page * address. @@ -189,7 +189,7 @@ int up_shmat(uintptr_t *pages, unsigned int npages, uintptr_t vaddr) int up_shmdt(uintptr_t vaddr, unsigned int npages) { struct tcb_s *tcb = nxsched_self(); - struct task_group_s *group; + struct arch_addrenv_s *addrenv; uintptr_t *l1entry; uint32_t *l2table; irqstate_t flags; @@ -201,11 +201,11 @@ int up_shmdt(uintptr_t vaddr, unsigned int npages) /* Sanity checks */ - DEBUGASSERT(npages > 0 && tcb && tcb->group); + DEBUGASSERT(npages > 0 && tcb && tcb->addrenv_own); DEBUGASSERT(vaddr >= CONFIG_ARCH_SHM_VBASE && vaddr < ARCH_SHM_VEND); DEBUGASSERT(MM_ISALIGNED(vaddr)); - group = tcb->group; + addrenv = &tcb->addrenv_own->addrenv; /* Loop until all pages have been unmapped from the caller's address * space. @@ -219,7 +219,7 @@ int up_shmdt(uintptr_t vaddr, unsigned int npages) /* Get the level 1 page table entry for this virtual address */ - l1entry = group->tg_addrenv.shm[shmndx]; + l1entry = addrenv->shm[shmndx]; DEBUGASSERT(l1entry != NULL); /* Get the physical address of the L2 page table from the L1 page diff --git a/arch/arm/src/armv7-a/arm_doirq.c b/arch/arm/src/armv7-a/arm_doirq.c index 17b5759e22..94df1c1224 100644 --- a/arch/arm/src/armv7-a/arm_doirq.c +++ b/arch/arm/src/armv7-a/arm_doirq.c @@ -28,13 +28,13 @@ #include #include +#include #include #include #include #include #include "arm_internal.h" -#include "group/group.h" #include "gic.h" /**************************************************************************** @@ -85,7 +85,7 @@ uint32_t *arm_doirq(int irq, uint32_t *regs) * thread at the head of the ready-to-run list. */ - group_addrenv(NULL); + addrenv_switch(NULL); } #endif diff --git a/arch/arm/src/armv7-a/arm_pgalloc.c b/arch/arm/src/armv7-a/arm_pgalloc.c index 35609ee6c3..8e7af3b4be 100644 --- a/arch/arm/src/armv7-a/arm_pgalloc.c +++ b/arch/arm/src/armv7-a/arm_pgalloc.c @@ -183,16 +183,16 @@ static int get_pgtable(arch_addrenv_t *addrenv, uintptr_t vaddr) uintptr_t pgalloc(uintptr_t brkaddr, unsigned int npages) { struct tcb_s *tcb = nxsched_self(); - struct task_group_s *group; + struct arch_addrenv_s *addrenv; uint32_t *l2table; irqstate_t flags; uintptr_t paddr; unsigned int index; - binfo("tcb->pid=%d tcb->group=%p\n", tcb->pid, tcb->group); + binfo("tcb->pid=%d tcb->group=%p\n", tcb->pid, tcb->addrenv_own); binfo("brkaddr=%x npages=%d\n", brkaddr, npages); - DEBUGASSERT(tcb && tcb->group); - group = tcb->group; + DEBUGASSERT(tcb && tcb->addrenv_own); + addrenv = &tcb->addrenv_own->addrenv; /* The current implementation only supports extending the user heap * region as part of the implementation of user sbrk(). This function @@ -200,8 +200,6 @@ uintptr_t pgalloc(uintptr_t brkaddr, unsigned int npages) * space and (2) extending the kernel memory regions as well. */ - DEBUGASSERT((group->tg_flags & GROUP_FLAG_ADDRENV) != 0); - /* brkaddr = 0 means that no heap has yet been allocated */ if (brkaddr == 0) @@ -216,7 +214,7 @@ uintptr_t pgalloc(uintptr_t brkaddr, unsigned int npages) { /* Get the physical address of the level 2 page table */ - paddr = get_pgtable(&group->tg_addrenv, brkaddr); + paddr = get_pgtable(addrenv, brkaddr); binfo("l2 page table (paddr=%x)\n", paddr); binfo("brkaddr=%x\n", brkaddr); if (paddr == 0) diff --git a/arch/arm/src/armv7-a/arm_syscall.c b/arch/arm/src/armv7-a/arm_syscall.c index 55d54d9c96..14ab2ffdb2 100644 --- a/arch/arm/src/armv7-a/arm_syscall.c +++ b/arch/arm/src/armv7-a/arm_syscall.c @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -38,7 +39,6 @@ #include "addrenv.h" #include "arm.h" #include "arm_internal.h" -#include "group/group.h" #include "signal/signal.h" /**************************************************************************** @@ -596,7 +596,7 @@ uint32_t *arm_syscall(uint32_t *regs) * thread at the head of the ready-to-run list. */ - group_addrenv(NULL); + addrenv_switch(NULL); } #endif diff --git a/arch/arm/src/armv7-r/arm_doirq.c b/arch/arm/src/armv7-r/arm_doirq.c index d601badb67..f7b2d5f881 100644 --- a/arch/arm/src/armv7-r/arm_doirq.c +++ b/arch/arm/src/armv7-r/arm_doirq.c @@ -33,7 +33,6 @@ #include #include "arm_internal.h" -#include "group/group.h" /**************************************************************************** * Public Functions diff --git a/arch/arm/src/common/arm_checkstack.c b/arch/arm/src/common/arm_checkstack.c index 51ac999511..7cc2a3973b 100644 --- a/arch/arm/src/common/arm_checkstack.c +++ b/arch/arm/src/common/arm_checkstack.c @@ -207,7 +207,7 @@ size_t up_check_tcbstack(struct tcb_s *tcb) if ((tcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_KERNEL) { - up_addrenv_select(&tcb->group->tg_addrenv, &oldenv); + up_addrenv_select(&tcb->addrenv_own->addrenv, &oldenv); saved = true; } #endif diff --git a/arch/risc-v/src/common/riscv_addrenv.c b/arch/risc-v/src/common/riscv_addrenv.c index c01a00fbd9..786f3c5713 100644 --- a/arch/risc-v/src/common/riscv_addrenv.c +++ b/arch/risc-v/src/common/riscv_addrenv.c @@ -824,7 +824,7 @@ int up_addrenv_clone(const arch_addrenv_t *src, * group. * * Input Parameters: - * group - The task group to which the new thread belongs. + * ptcb - The tcb of the parent task. * tcb - The tcb of the thread needing the address environment. * * Returned Value: @@ -832,7 +832,7 @@ int up_addrenv_clone(const arch_addrenv_t *src, * ****************************************************************************/ -int up_addrenv_attach(struct task_group_s *group, struct tcb_s *tcb) +int up_addrenv_attach(struct tcb_s *ptcb, struct tcb_s *tcb) { /* There is nothing that needs to be done */ @@ -849,12 +849,7 @@ int up_addrenv_attach(struct task_group_s *group, struct tcb_s *tcb) * task group is itself destroyed. Any resources unique to this thread * may be destroyed now. * - * NOTE: In some platforms, nothing will need to be done in this case. - * Simply being a member of the group that has the address environment - * may be sufficient. - * * Input Parameters: - * group - The group to which the thread belonged. * tcb - The TCB of the task or thread whose the address environment will * be released. * @@ -863,7 +858,7 @@ int up_addrenv_attach(struct task_group_s *group, struct tcb_s *tcb) * ****************************************************************************/ -int up_addrenv_detach(struct task_group_s *group, struct tcb_s *tcb) +int up_addrenv_detach(struct tcb_s *tcb) { /* There is nothing that needs to be done */ diff --git a/arch/risc-v/src/common/riscv_addrenv_shm.c b/arch/risc-v/src/common/riscv_addrenv_shm.c index 170e88b3ea..0183537db2 100644 --- a/arch/risc-v/src/common/riscv_addrenv_shm.c +++ b/arch/risc-v/src/common/riscv_addrenv_shm.c @@ -66,21 +66,21 @@ int up_shmat(uintptr_t *pages, unsigned int npages, uintptr_t vaddr) { - struct tcb_s *tcb = nxsched_self(); - struct task_group_s *group; - uintptr_t ptlast; - uintptr_t ptlevel; - uintptr_t paddr; + struct tcb_s *tcb = nxsched_self(); + struct arch_addrenv_s *addrenv; + uintptr_t ptlast; + uintptr_t ptlevel; + uintptr_t paddr; /* Sanity checks */ - DEBUGASSERT(tcb && tcb->group); + DEBUGASSERT(tcb && tcb->addrenv_own); DEBUGASSERT(pages != NULL && npages > 0); DEBUGASSERT(vaddr >= CONFIG_ARCH_SHM_VBASE && vaddr < ARCH_SHM_VEND); DEBUGASSERT(MM_ISALIGNED(vaddr)); - group = tcb->group; - ptlevel = RV_MMU_PT_LEVELS; + addrenv = &tcb->addrenv_own->addrenv; + ptlevel = RV_MMU_PT_LEVELS; /* Add the references to pages[] into the caller's address environment */ @@ -88,7 +88,7 @@ int up_shmat(uintptr_t *pages, unsigned int npages, uintptr_t vaddr) { /* Get the address of the last level page table */ - ptlast = riscv_pgvaddr(riscv_get_pgtable(&group->tg_addrenv, vaddr)); + ptlast = riscv_pgvaddr(riscv_get_pgtable(addrenv, vaddr)); if (!ptlast) { return -ENOMEM; @@ -127,23 +127,23 @@ int up_shmat(uintptr_t *pages, unsigned int npages, uintptr_t vaddr) int up_shmdt(uintptr_t vaddr, unsigned int npages) { - struct tcb_s *tcb = nxsched_self(); - struct task_group_s *group; - uintptr_t ptlast; - uintptr_t ptprev; - uintptr_t ptlevel; - uintptr_t paddr; + struct tcb_s *tcb = nxsched_self(); + struct arch_addrenv_s *addrenv; + uintptr_t ptlast; + uintptr_t ptprev; + uintptr_t ptlevel; + uintptr_t paddr; /* Sanity checks */ - DEBUGASSERT(tcb && tcb->group); + DEBUGASSERT(tcb && tcb->addrenv_own); DEBUGASSERT(npages > 0); DEBUGASSERT(vaddr >= CONFIG_ARCH_SHM_VBASE && vaddr < ARCH_SHM_VEND); DEBUGASSERT(MM_ISALIGNED(vaddr)); - group = tcb->group; - ptlevel = ARCH_SPGTS; - ptprev = riscv_pgvaddr(group->tg_addrenv.spgtables[ARCH_SPGTS - 1]); + addrenv = &tcb->addrenv_own->addrenv; + ptlevel = ARCH_SPGTS; + ptprev = riscv_pgvaddr(addrenv->spgtables[ARCH_SPGTS - 1]); if (!ptprev) { /* Something is very wrong */ diff --git a/arch/risc-v/src/common/riscv_checkstack.c b/arch/risc-v/src/common/riscv_checkstack.c index 4aaf59c639..f662528ab2 100644 --- a/arch/risc-v/src/common/riscv_checkstack.c +++ b/arch/risc-v/src/common/riscv_checkstack.c @@ -163,7 +163,7 @@ size_t up_check_tcbstack(struct tcb_s *tcb) if ((tcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_KERNEL) { - up_addrenv_select(&tcb->group->tg_addrenv, &oldenv); + up_addrenv_select(&tcb->addrenv_own->addrenv, &oldenv); saved = true; } #endif diff --git a/arch/risc-v/src/common/riscv_doirq.c b/arch/risc-v/src/common/riscv_doirq.c index 4dad4c6887..a1faf2aa0c 100644 --- a/arch/risc-v/src/common/riscv_doirq.c +++ b/arch/risc-v/src/common/riscv_doirq.c @@ -28,12 +28,12 @@ #include #include +#include #include #include #include #include "riscv_internal.h" -#include "group/group.h" /**************************************************************************** * Pre-processor Definitions @@ -98,7 +98,7 @@ uintptr_t *riscv_doirq(int irq, uintptr_t *regs) * thread at the head of the ready-to-run list. */ - group_addrenv(NULL); + addrenv_switch(NULL); } #endif diff --git a/arch/risc-v/src/common/riscv_pgalloc.c b/arch/risc-v/src/common/riscv_pgalloc.c index e66939c8ed..9f74f4db87 100644 --- a/arch/risc-v/src/common/riscv_pgalloc.c +++ b/arch/risc-v/src/common/riscv_pgalloc.c @@ -94,14 +94,14 @@ uintptr_t pgalloc(uintptr_t brkaddr, unsigned int npages) { - struct tcb_s *tcb = nxsched_self(); - struct task_group_s *group; - uintptr_t ptlast; - uintptr_t paddr; - uintptr_t vaddr; + struct tcb_s *tcb = nxsched_self(); + struct arch_addrenv_s *addrenv; + uintptr_t ptlast; + uintptr_t paddr; + uintptr_t vaddr; - DEBUGASSERT(tcb && tcb->group); - group = tcb->group; + DEBUGASSERT(tcb && tcb->addrenv_own); + addrenv = &tcb->addrenv_own->addrenv; /* The current implementation only supports extending the user heap * region as part of the implementation of user sbrk(). This function @@ -109,13 +109,11 @@ uintptr_t pgalloc(uintptr_t brkaddr, unsigned int npages) * space and (2) extending the kernel memory regions as well. */ - DEBUGASSERT((group->tg_flags & GROUP_FLAG_ADDRENV) != 0); - /* brkaddr = 0 means that no heap has yet been allocated */ if (!brkaddr) { - brkaddr = group->tg_addrenv.heapvbase; + brkaddr = addrenv->heapvbase; } /* Start mapping from the old heap break address */ @@ -124,14 +122,14 @@ uintptr_t pgalloc(uintptr_t brkaddr, unsigned int npages) /* Sanity checks */ - DEBUGASSERT(brkaddr >= group->tg_addrenv.heapvbase); + DEBUGASSERT(brkaddr >= addrenv->heapvbase); DEBUGASSERT(MM_ISALIGNED(brkaddr)); for (; npages > 0; npages--) { /* Get the address of the last level page table */ - ptlast = riscv_pgvaddr(riscv_get_pgtable(&group->tg_addrenv, vaddr)); + ptlast = riscv_pgvaddr(riscv_get_pgtable(addrenv, vaddr)); if (!ptlast) { return 0; diff --git a/arch/risc-v/src/common/supervisor/riscv_perform_syscall.c b/arch/risc-v/src/common/supervisor/riscv_perform_syscall.c index 89dfd6ca5e..88d8be77ee 100644 --- a/arch/risc-v/src/common/supervisor/riscv_perform_syscall.c +++ b/arch/risc-v/src/common/supervisor/riscv_perform_syscall.c @@ -26,8 +26,9 @@ #include +#include + #include "riscv_internal.h" -#include "group/group.h" /**************************************************************************** * Public Functions @@ -52,7 +53,7 @@ void *riscv_perform_syscall(uintptr_t *regs) * thread at the head of the ready-to-run list. */ - group_addrenv(NULL); + addrenv_switch(NULL); } #endif diff --git a/arch/z80/src/common/z80_doirq.c b/arch/z80/src/common/z80_doirq.c index f441b28b8e..106993f359 100644 --- a/arch/z80/src/common/z80_doirq.c +++ b/arch/z80/src/common/z80_doirq.c @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -35,7 +36,6 @@ #include "chip/switch.h" #include "z80_internal.h" -#include "group/group.h" /**************************************************************************** * Public Functions @@ -82,7 +82,7 @@ FAR chipreg_t *z80_doirq(uint8_t irq, FAR chipreg_t *regs) * ready-to-run list. */ - group_addrenv(NULL); + addrenv_switch(NULL); } regs = newregs; diff --git a/arch/z80/src/common/z80_exit.c b/arch/z80/src/common/z80_exit.c index 6843ba0ae8..ffe5f77e75 100644 --- a/arch/z80/src/common/z80_exit.c +++ b/arch/z80/src/common/z80_exit.c @@ -28,6 +28,7 @@ #include #include +#include #include #include #ifdef CONFIG_DUMP_ON_EXIT @@ -143,7 +144,7 @@ void up_exit(int status) * the ready-to-run list. */ - group_addrenv(tcb); + addrenv_switch(tcb); #endif /* Then switch contexts */ diff --git a/arch/z80/src/common/z80_switchcontext.c b/arch/z80/src/common/z80_switchcontext.c index 6415eca1ef..fde1cd3c0d 100644 --- a/arch/z80/src/common/z80_switchcontext.c +++ b/arch/z80/src/common/z80_switchcontext.c @@ -28,13 +28,13 @@ #include #include +#include #include #include #include "chip.h" #include "chip/switch.h" #include "sched/sched.h" -#include "group/group.h" #include "clock/clock.h" #include "z80_internal.h" @@ -99,7 +99,7 @@ void up_switch_context(FAR struct tcb_s *tcb, FAR struct tcb_s *rtcb) * thread at the head of the ready-to-run list. */ - group_addrenv(tcb); + addrenv_switch(tcb); #endif /* Update scheduler parameters */ diff --git a/arch/z80/src/z180/z180_mmu.c b/arch/z80/src/z180/z180_mmu.c index a93a08850f..ccc016405c 100644 --- a/arch/z80/src/z180/z180_mmu.c +++ b/arch/z80/src/z180/z180_mmu.c @@ -560,7 +560,7 @@ int up_addrenv_clone(FAR const arch_addrenv_t *src, * group. * * Input Parameters: - * group - The task group to which the new thread belongs. + * ptcb - The tcb of the parent task. * tcb - The tcb of the thread needing the address environment. * * Returned Value: @@ -568,7 +568,7 @@ int up_addrenv_clone(FAR const arch_addrenv_t *src, * ****************************************************************************/ -int up_addrenv_attach(FAR struct task_group_s *group, FAR struct tcb_s *tcb) +int up_addrenv_attach(FAR struct tcb_s *ptcb, FAR struct tcb_s *tcb) { /* There is nothing that needs to be done */ @@ -590,7 +590,6 @@ int up_addrenv_attach(FAR struct task_group_s *group, FAR struct tcb_s *tcb) * may be sufficient. * * Input Parameters: - * group - The group to which the thread belonged. * tcb - The TCB of the task or thread whose the address environment will * be released. * @@ -599,7 +598,7 @@ int up_addrenv_attach(FAR struct task_group_s *group, FAR struct tcb_s *tcb) * ****************************************************************************/ -int up_addrenv_detach(FAR struct task_group_s *group, FAR struct tcb_s *tcb) +int up_addrenv_detach(FAR struct tcb_s *tcb) { /* There is nothing that needs to be done */ diff --git a/binfmt/binfmt_execmodule.c b/binfmt/binfmt_execmodule.c index df24121c79..3736441a9a 100644 --- a/binfmt/binfmt_execmodule.c +++ b/binfmt/binfmt_execmodule.c @@ -239,18 +239,14 @@ int exec_module(FAR const struct binary_s *binp, #endif #ifdef CONFIG_ARCH_ADDRENV - /* Assign the address environment to the new task group */ + /* Attach the address environment to the new task */ - ret = up_addrenv_clone(&binp->addrenv, &tcb->cmn.group->tg_addrenv); + ret = addrenv_attach((FAR struct tcb_s *)tcb, &binp->addrenv); if (ret < 0) { - berr("ERROR: up_addrenv_clone() failed: %d\n", ret); + berr("ERROR: addrenv_attach() failed: %d\n", ret); goto errout_with_tcbinit; } - - /* Mark that this group has an address environment */ - - tcb->cmn.group->tg_flags |= GROUP_FLAG_ADDRENV; #endif #ifdef CONFIG_BINFMT_CONSTRUCTORS diff --git a/include/nuttx/addrenv.h b/include/nuttx/addrenv.h index cc10d0e8aa..c1e6c5d5c4 100644 --- a/include/nuttx/addrenv.h +++ b/include/nuttx/addrenv.h @@ -32,6 +32,8 @@ # include #endif +#include + #ifdef CONFIG_ARCH_ADDRENV /**************************************************************************** @@ -218,6 +220,11 @@ (CONFIG_ARCH_PGPOOL_VBASE + CONFIG_ARCH_PGPOOL_SIZE) #endif +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +struct tcb_s; /* Forward reference to TCB */ /**************************************************************************** * Public Types @@ -225,6 +232,13 @@ #ifndef __ASSEMBLY__ +struct addrenv_s +{ + struct arch_addrenv_s addrenv; /* The address environment page directory */ +}; + +typedef struct addrenv_s addrenv_t; + /* Reserved .bss/.data region. In the kernel build (CONFIG_BUILD_KERNEL), * the region at the beginning of the .bss/.data region is reserved for use * by the OS. This reserved region contains support for: @@ -269,6 +283,83 @@ struct addrenv_reserve_s * Public Function Prototypes ****************************************************************************/ +/**************************************************************************** + * Name: addrenv_allocate + * + * Description: + * Allocate an address environment for a new process. + * + * Input Parameters: + * tcb - The tcb of the newly created task. + * ttype - The type of the task. + * + * Returned Value: + * This is a NuttX internal function so it follows the convention that + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +int addrenv_allocate(FAR struct tcb_s *tcb, uint8_t ttype); + +/**************************************************************************** + * Name: addrenv_free + * + * Description: + * Free an address environment for a process. + * + * Input Parameters: + * tcb - The tcb of the task. + * + * Returned Value: + * This is a NuttX internal function so it follows the convention that + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +int addrenv_free(FAR struct tcb_s *tcb); + +/**************************************************************************** + * Name: addrenv_switch + * + * Description: + * Switch to an address environment. + * + * Input Parameters: + * tcb - The tcb of the task to switch to, or NULL to use the task at the + * head of the ready-to-run list. + * + * Returned Value: + * This is a NuttX internal function so it follows the convention that + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +int addrenv_switch(FAR struct tcb_s *tcb); + +/**************************************************************************** + * Name: addrenv_attach + * + * Description: + * Attach address environment to a newly process. Called by exec() right + * before injecting the new process into the system. + * + * Input Parameters: + * tcb - The tcb of the newly loaded task. + * addrenv - The address environment that is attached. + * + * Returned Value: + * This is a NuttX internal function so it follows the convention that + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +int addrenv_attach(FAR struct tcb_s *tcb, + FAR const struct arch_addrenv_s *addrenv); + /**************************************************************************** * Address Environment Interfaces * diff --git a/include/nuttx/arch.h b/include/nuttx/arch.h index 107daf0fd7..c0474f86b1 100644 --- a/include/nuttx/arch.h +++ b/include/nuttx/arch.h @@ -1094,13 +1094,9 @@ int up_addrenv_clone(FAR const arch_addrenv_t *src, * is created that needs to share the address environment of its task * group. * - * NOTE: In some platforms, nothing will need to be done in this case. - * Simply being a member of the group that has the address environment - * may be sufficient. - * * Input Parameters: - * group - The task group to which the new thread belongs. - * tcb - The TCB of the thread needing the address environment. + * ptcb - The tcb of the parent task. + * tcb - The tcb of the thread needing the address environment. * * Returned Value: * Zero (OK) on success; a negated errno value on failure. @@ -1108,7 +1104,7 @@ int up_addrenv_clone(FAR const arch_addrenv_t *src, ****************************************************************************/ #ifdef CONFIG_ARCH_ADDRENV -int up_addrenv_attach(FAR struct task_group_s *group, FAR struct tcb_s *tcb); +int up_addrenv_attach(FAR struct tcb_s *ptcb, FAR struct tcb_s *tcb); #endif /**************************************************************************** @@ -1121,12 +1117,7 @@ int up_addrenv_attach(FAR struct task_group_s *group, FAR struct tcb_s *tcb); * task group is itself destroyed. Any resources unique to this thread * may be destroyed now. * - * NOTE: In some platforms, nothing will need to be done in this case. - * Simply being a member of the group that has the address environment - * may be sufficient. - * * Input Parameters: - * group - The group to which the thread belonged. * tcb - The TCB of the task or thread whose the address environment will * be released. * @@ -1136,7 +1127,7 @@ int up_addrenv_attach(FAR struct task_group_s *group, FAR struct tcb_s *tcb); ****************************************************************************/ #ifdef CONFIG_ARCH_ADDRENV -int up_addrenv_detach(FAR struct task_group_s *group, FAR struct tcb_s *tcb); +int up_addrenv_detach(FAR struct tcb_s *tcb); #endif /**************************************************************************** diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index 5a33418af8..b3aa69283d 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -107,10 +108,9 @@ /* Values for struct task_group tg_flags */ #define GROUP_FLAG_NOCLDWAIT (1 << 0) /* Bit 0: Do not retain child exit status */ -#define GROUP_FLAG_ADDRENV (1 << 1) /* Bit 1: Group has an address environment */ -#define GROUP_FLAG_PRIVILEGED (1 << 2) /* Bit 2: Group is privileged */ -#define GROUP_FLAG_DELETED (1 << 3) /* Bit 3: Group has been deleted but not yet freed */ - /* Bits 4-7: Available */ +#define GROUP_FLAG_PRIVILEGED (1 << 1) /* Bit 1: Group is privileged */ +#define GROUP_FLAG_DELETED (1 << 2) /* Bit 2: Group has been deleted but not yet freed */ + /* Bits 3-7: Available */ /* Values for struct child_status_s ch_flags */ @@ -418,7 +418,7 @@ struct binary_s; /* Forward reference struct task_group_s { -#if defined(HAVE_GROUP_MEMBERS) || defined(CONFIG_ARCH_ADDRENV) +#if defined(HAVE_GROUP_MEMBERS) struct task_group_s *flink; /* Supports a singly linked list */ #endif pid_t tg_pid; /* The ID of the task within the group */ @@ -512,12 +512,6 @@ struct task_group_s struct filelist tg_filelist; /* Maps file descriptor to file */ -#ifdef CONFIG_ARCH_ADDRENV - /* Address Environment ****************************************************/ - - arch_addrenv_t tg_addrenv; /* Task group address environment */ -#endif - /* Virtual memory mapping info ********************************************/ struct mm_map_s tg_mm_map; /* Task mmappings */ @@ -542,6 +536,12 @@ struct tcb_s FAR struct task_group_s *group; /* Pointer to shared task group data */ + /* Address Environment ****************************************************/ + +#ifdef CONFIG_ARCH_ADDRENV + FAR struct addrenv_s *addrenv_own; /* Task (group) own memory mappings */ +#endif + /* Task Management Fields *************************************************/ pid_t pid; /* This is the ID of the thread */ diff --git a/sched/Makefile b/sched/Makefile index 2e7c19282a..ccd723f9d6 100644 --- a/sched/Makefile +++ b/sched/Makefile @@ -20,6 +20,7 @@ include $(TOPDIR)/Make.defs +include addrenv/Make.defs include clock/Make.defs include environ/Make.defs include group/Make.defs diff --git a/sched/addrenv/Make.defs b/sched/addrenv/Make.defs new file mode 100644 index 0000000000..e221ea1c97 --- /dev/null +++ b/sched/addrenv/Make.defs @@ -0,0 +1,28 @@ +############################################################################ +# sched/addrenv/Make.defs +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +ifeq ($(CONFIG_ARCH_ADDRENV),y) +CSRCS += addrenv.c +endif + +# Include addrenv build support + +DEPPATH += --dep-path addrenv +VPATH += :addrenv diff --git a/sched/group/group_addrenv.c b/sched/addrenv/addrenv.c similarity index 52% rename from sched/group/group_addrenv.c rename to sched/addrenv/addrenv.c index 41cd4a0ce2..0b7fb18052 100644 --- a/sched/group/group_addrenv.c +++ b/sched/addrenv/addrenv.c @@ -1,5 +1,5 @@ /**************************************************************************** - * sched/group/group_addrenv.c + * sched/addrenv/addrenv.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -27,33 +27,37 @@ #include #include +#include #include #include #include "sched/sched.h" -#include "group/group.h" - -#ifdef CONFIG_ARCH_ADDRENV /**************************************************************************** - * Public Data + * Pre-processor Definitions ****************************************************************************/ -/* This variable holds the current task group. This pointer is NULL - * if the current task is a kernel thread that has no address environment - * (other than the kernel context). +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* This variable holds the current address environment. These contents are + * _never_ NULL, besides when the system is started and there are only the + * initial kernel mappings available. * * This must only be accessed with interrupts disabled. + * + * REVISIT: Try to get rid of this, global bookkeeping for this is dangerous. */ -FAR struct task_group_s *g_group_current[CONFIG_SMP_NCPUS]; +static FAR struct addrenv_s *g_addrenv[CONFIG_SMP_NCPUS]; /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** - * Name: group_addrenv + * Name: addrenv_switch * * Description: * Instantiate the group address environment for the current thread at the @@ -80,10 +84,10 @@ FAR struct task_group_s *g_group_current[CONFIG_SMP_NCPUS]; * ****************************************************************************/ -int group_addrenv(FAR struct tcb_s *tcb) +int addrenv_switch(FAR struct tcb_s *tcb) { - FAR struct task_group_s *group; - FAR struct task_group_s *oldgroup; + FAR struct addrenv_s *curr; + FAR struct addrenv_s *next; irqstate_t flags; int cpu; int ret; @@ -97,12 +101,12 @@ int group_addrenv(FAR struct tcb_s *tcb) tcb = this_task(); } - DEBUGASSERT(tcb && tcb->group); - group = tcb->group; + DEBUGASSERT(tcb); + next = tcb->mm_curr; /* Does the group have an address environment? */ - if ((group->tg_flags & GROUP_FLAG_ADDRENV) == 0) + if (!next) { /* No... just return perhaps leaving a different address environment * intact. @@ -111,24 +115,24 @@ int group_addrenv(FAR struct tcb_s *tcb) return OK; } - /* Are we going to change address environments? */ - flags = enter_critical_section(); cpu = this_cpu(); - oldgroup = g_group_current[cpu]; - if (group != oldgroup) + curr = g_addrenv[cpu]; + + /* Are we going to change address environments? */ + + if (curr != next) { /* Yes.. Is there a current address environment in place? */ - if (oldgroup) + if (curr) { /* We need to flush the D-Cache and Invalidate the I-Cache for * the group whose environment is disappearing. */ - DEBUGASSERT((oldgroup->tg_flags & GROUP_FLAG_ADDRENV) != 0); - up_addrenv_coherent(&oldgroup->tg_addrenv); + up_addrenv_coherent(&curr->addrenv); } /* Instantiate the new address environment (removing the old @@ -137,19 +141,115 @@ int group_addrenv(FAR struct tcb_s *tcb) * instantiated. */ - ret = up_addrenv_select(&group->tg_addrenv, NULL); + ret = up_addrenv_select(&next->addrenv, NULL); if (ret < 0) { berr("ERROR: up_addrenv_select failed: %d\n", ret); } - /* Save the new, current group */ + /* Save the new, current address environment group */ - g_group_current[cpu] = group; + g_addrenv[cpu] = next; } leave_critical_section(flags); return OK; } -#endif /* CONFIG_ARCH_ADDRENV */ +/**************************************************************************** + * Name: addrenv_allocate + * + * Description: + * Allocate an address environment for a new process. + * + * Input Parameters: + * tcb - The tcb of the newly created task. + * ttype - The type of the task. + * + * Returned Value: + * This is a NuttX internal function so it follows the convention that + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +int addrenv_allocate(FAR struct tcb_s *tcb, uint8_t ttype) +{ + int ret = OK; + + if ((ttype & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_KERNEL) + { + tcb->addrenv_own = NULL; + } + else + { + tcb->addrenv_own = (FAR struct addrenv_s *) + kmm_zalloc(sizeof(struct addrenv_s)); + if (tcb->addrenv_own == NULL) + { + ret = -ENOMEM; + } + } + + return ret; +} + +/**************************************************************************** + * Name: addrenv_free + * + * Description: + * Free an address environment for a process. + * + * Input Parameters: + * tcb - The tcb of the task. + * + * Returned Value: + * This is a NuttX internal function so it follows the convention that + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +int addrenv_free(FAR struct tcb_s *tcb) +{ + if (tcb->addrenv_own != NULL) + { + kmm_free(tcb->addrenv_own); + } + + return OK; +} + +/**************************************************************************** + * Name: addrenv_attach + * + * Description: + * Attach address environment to a newly created group. Called by exec() + * right before injecting the new process into the system. + * + * Input Parameters: + * tcb - The tcb of the newly loaded task. + * addrenv - The address environment that is attached. + * + * Returned Value: + * This is a NuttX internal function so it follows the convention that + * 0 (OK) is returned on success and a negated errno is returned on + * failure. + * + ****************************************************************************/ + +int addrenv_attach(FAR struct tcb_s *tcb, + FAR const struct arch_addrenv_s *addrenv) +{ + int ret; + + /* Clone the address environment for us */ + + ret = up_addrenv_clone(addrenv, &tcb->addrenv_own->addrenv); + if (ret < 0) + { + berr("ERROR: up_addrenv_clone failed: %d\n", ret); + } + + return OK; +} diff --git a/sched/group/Make.defs b/sched/group/Make.defs index 5d61466b2a..016fb98c7f 100644 --- a/sched/group/Make.defs +++ b/sched/group/Make.defs @@ -36,10 +36,6 @@ ifeq ($(CONFIG_SCHED_USER_IDENTITY),y) CSRCS += group_setuid.c group_setgid.c group_getuid.c group_getgid.c endif -ifeq ($(CONFIG_ARCH_ADDRENV),y) -CSRCS += group_addrenv.c -endif - ifeq ($(CONFIG_SIG_SIGSTOP_ACTION),y) CSRCS += group_suspendchildren.c group_continue.c endif diff --git a/sched/group/group.h b/sched/group/group.h index 7ce4a31b58..ee865dad9e 100644 --- a/sched/group/group.h +++ b/sched/group/group.h @@ -44,23 +44,12 @@ typedef int (*foreachchild_t)(pid_t pid, FAR void *arg); * Public Data ****************************************************************************/ -#if defined(HAVE_GROUP_MEMBERS) || defined(CONFIG_ARCH_ADDRENV) +#if defined(HAVE_GROUP_MEMBERS) /* This is the head of a list of all group members */ extern FAR struct task_group_s *g_grouphead; #endif -#ifdef CONFIG_ARCH_ADDRENV -/* This variable holds the current task group. This pointer is NULL - * if the current task is a kernel thread that has no address environment - * (other than the kernel context). - * - * This must only be accessed with interrupts disabled. - */ - -extern FAR struct task_group_s *g_group_current[CONFIG_SMP_NCPUS]; -#endif - /**************************************************************************** * Public Function Prototypes ****************************************************************************/ @@ -86,7 +75,7 @@ void group_add_waiter(FAR struct task_group_s *group); void group_del_waiter(FAR struct task_group_s *group); #endif -#if defined(HAVE_GROUP_MEMBERS) || defined(CONFIG_ARCH_ADDRENV) +#if defined(HAVE_GROUP_MEMBERS) FAR struct task_group_s *group_findbypid(pid_t pid); #endif @@ -100,12 +89,6 @@ int group_continue(FAR struct tcb_s *tcb); #endif #endif -#ifdef CONFIG_ARCH_ADDRENV -/* Group address environment management */ - -int group_addrenv(FAR struct tcb_s *tcb); -#endif - /* Convenience functions */ FAR struct task_group_s *task_getgroup(pid_t pid); diff --git a/sched/group/group_create.c b/sched/group/group_create.c index 9a35f82788..f353df0ca8 100644 --- a/sched/group/group_create.c +++ b/sched/group/group_create.c @@ -51,7 +51,7 @@ * Public Data ****************************************************************************/ -#if defined(HAVE_GROUP_MEMBERS) || defined(CONFIG_ARCH_ADDRENV) +#if defined(HAVE_GROUP_MEMBERS) /* This is the head of a list of all group members */ FAR struct task_group_s *g_grouphead; @@ -231,7 +231,7 @@ errout_with_group: void group_initialize(FAR struct task_tcb_s *tcb) { FAR struct task_group_s *group; -#if defined(HAVE_GROUP_MEMBERS) || defined(CONFIG_ARCH_ADDRENV) +#if defined(HAVE_GROUP_MEMBERS) irqstate_t flags; #endif @@ -261,7 +261,7 @@ void group_initialize(FAR struct task_tcb_s *tcb) group->tg_nmembers = 1; -#if defined(HAVE_GROUP_MEMBERS) || defined(CONFIG_ARCH_ADDRENV) +#if defined(HAVE_GROUP_MEMBERS) /* Add the initialized entry to the list of groups */ flags = enter_critical_section(); diff --git a/sched/group/group_find.c b/sched/group/group_find.c index e25cc3e36e..822ee91d31 100644 --- a/sched/group/group_find.c +++ b/sched/group/group_find.c @@ -63,7 +63,7 @@ * ****************************************************************************/ -#if defined(HAVE_GROUP_MEMBERS) || defined(CONFIG_ARCH_ADDRENV) +#if defined(HAVE_GROUP_MEMBERS) FAR struct task_group_s *group_findbypid(pid_t pid) { FAR struct task_group_s *group; diff --git a/sched/group/group_leave.c b/sched/group/group_leave.c index dd5eedb74d..0f3337a43e 100644 --- a/sched/group/group_leave.c +++ b/sched/group/group_leave.c @@ -67,7 +67,7 @@ * ****************************************************************************/ -#if defined(HAVE_GROUP_MEMBERS) || defined(CONFIG_ARCH_ADDRENV) +#if defined(HAVE_GROUP_MEMBERS) static void group_remove(FAR struct task_group_s *group) { FAR struct task_group_s *curr; @@ -128,10 +128,6 @@ static void group_remove(FAR struct task_group_s *group) static inline void group_release(FAR struct task_group_s *group) { -#ifdef CONFIG_ARCH_ADDRENV - int i; -#endif - #if CONFIG_TLS_TASK_NELEM > 0 task_tls_destruct(); #endif @@ -172,7 +168,7 @@ static inline void group_release(FAR struct task_group_s *group) mm_map_destroy(&group->tg_mm_map); -#if defined(HAVE_GROUP_MEMBERS) || defined(CONFIG_ARCH_ADDRENV) +#if defined(HAVE_GROUP_MEMBERS) /* Remove the group from the list of groups */ group_remove(group); @@ -201,22 +197,6 @@ static inline void group_release(FAR struct task_group_s *group) } #endif -#ifdef CONFIG_ARCH_ADDRENV - /* Destroy the group address environment */ - - up_addrenv_destroy(&group->tg_addrenv); - - /* Mark no address environment */ - - for (i = 0; i < CONFIG_SMP_NCPUS; i++) - { - if (group == g_group_current[i]) - { - g_group_current[i] = NULL; - } - } -#endif - /* Mark the group as deleted now */ group->tg_flags |= GROUP_FLAG_DELETED; diff --git a/sched/misc/assert.c b/sched/misc/assert.c index d7b906d5cb..b8f4c23148 100644 --- a/sched/misc/assert.c +++ b/sched/misc/assert.c @@ -242,7 +242,7 @@ static void get_argv_str(FAR struct tcb_s *tcb, FAR char *args, size_t size) #ifdef CONFIG_ARCH_ADDRENV if ((tcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_KERNEL) { - if ((tcb->group->tg_flags & GROUP_FLAG_ADDRENV) == 0) + if (tcb->addrenv_own == NULL) { /* Process should have address environment, but doesn't */ @@ -250,7 +250,7 @@ static void get_argv_str(FAR struct tcb_s *tcb, FAR char *args, size_t size) return; } - up_addrenv_select(&tcb->group->tg_addrenv, &oldenv); + up_addrenv_select(&tcb->addrenv_own->addrenv, &oldenv); saved = true; } #endif diff --git a/sched/pthread/pthread_create.c b/sched/pthread/pthread_create.c index 99acf0cf51..5858dd4acf 100644 --- a/sched/pthread/pthread_create.c +++ b/sched/pthread/pthread_create.c @@ -220,7 +220,7 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, #ifdef CONFIG_ARCH_ADDRENV /* Share the address environment of the parent task group. */ - ret = up_addrenv_attach(ptcb->cmn.group, this_task()); + ret = up_addrenv_attach(this_task(), (FAR struct tcb_s *)ptcb); if (ret < 0) { errcode = -ret; diff --git a/sched/sched/sched_releasetcb.c b/sched/sched/sched_releasetcb.c index ab644ce783..fcee4461ab 100644 --- a/sched/sched/sched_releasetcb.c +++ b/sched/sched/sched_releasetcb.c @@ -154,7 +154,11 @@ int nxsched_release_tcb(FAR struct tcb_s *tcb, uint8_t ttype) #ifdef CONFIG_ARCH_ADDRENV /* Release this thread's reference to the address environment */ - ret = up_addrenv_detach(tcb->group, tcb); + ret = up_addrenv_detach(tcb); + if (ttype == TCB_FLAG_TTYPE_TASK) + { + addrenv_free(tcb); + } #endif /* Leave the group (if we did not already leave in task_exithook.c) */ diff --git a/sched/task/task_init.c b/sched/task/task_init.c index c5abafde65..95b0927cc0 100644 --- a/sched/task/task_init.c +++ b/sched/task/task_init.c @@ -96,12 +96,22 @@ int nxtask_init(FAR struct task_tcb_s *tcb, const char *name, int priority, DEBUGASSERT(tcb && ttype != TCB_FLAG_TTYPE_PTHREAD); #endif +#ifdef CONFIG_ARCH_ADDRENV + /* Allocate address environment for the task */ + + ret = addrenv_allocate(&tcb->cmn, tcb->cmn.flags); + if (ret < 0) + { + return ret; + } +#endif + /* Create a new task group */ ret = group_allocate(tcb, tcb->cmn.flags); if (ret < 0) { - return ret; + goto errout_with_addrenv; } /* Duplicate the parent tasks environment */ @@ -190,6 +200,11 @@ errout_with_group: } group_leave(&tcb->cmn); + +errout_with_addrenv: +#ifdef CONFIG_ARCH_ADDRENV + addrenv_free(&tcb->cmn); +#endif return ret; }