diff --git a/arch/arm/src/common/arm_checkstack.c b/arch/arm/src/common/arm_checkstack.c index 4c3400c4e4e..7e1f2e2000c 100644 --- a/arch/arm/src/common/arm_checkstack.c +++ b/arch/arm/src/common/arm_checkstack.c @@ -203,9 +203,11 @@ size_t up_check_tcbstack(struct tcb_s *tcb) size_t size; #ifdef CONFIG_ARCH_ADDRENV + FAR struct addrenv_s *oldenv; + if (tcb->addrenv_own != NULL) { - addrenv_select(tcb->addrenv_own); + addrenv_select(tcb->addrenv_own, &oldenv); } #endif @@ -214,7 +216,7 @@ size_t up_check_tcbstack(struct tcb_s *tcb) #ifdef CONFIG_ARCH_ADDRENV if (tcb->addrenv_own != NULL) { - addrenv_restore(); + addrenv_restore(oldenv); } #endif diff --git a/arch/risc-v/src/common/riscv_checkstack.c b/arch/risc-v/src/common/riscv_checkstack.c index 52978896ce7..57d2123d0fb 100644 --- a/arch/risc-v/src/common/riscv_checkstack.c +++ b/arch/risc-v/src/common/riscv_checkstack.c @@ -159,9 +159,11 @@ size_t up_check_tcbstack(struct tcb_s *tcb) size_t size; #ifdef CONFIG_ARCH_ADDRENV + FAR struct addrenv_s *oldenv; + if (tcb->addrenv_own != NULL) { - addrenv_select(tcb->addrenv_own); + addrenv_select(tcb->addrenv_own, &oldenv); } #endif @@ -171,7 +173,7 @@ size_t up_check_tcbstack(struct tcb_s *tcb) #ifdef CONFIG_ARCH_ADDRENV if (tcb->addrenv_own != NULL) { - addrenv_restore(); + addrenv_restore(oldenv); } #endif diff --git a/binfmt/binfmt_execmodule.c b/binfmt/binfmt_execmodule.c index bf6fbdc37fe..865b8a3f70d 100644 --- a/binfmt/binfmt_execmodule.c +++ b/binfmt/binfmt_execmodule.c @@ -165,7 +165,7 @@ int exec_module(FAR struct binary_s *binp, #if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL) /* Instantiate the address environment containing the user heap */ - ret = addrenv_select(binp->addrenv); + ret = addrenv_select(binp->addrenv, &binp->oldenv); if (ret < 0) { berr("ERROR: addrenv_select() failed: %d\n", ret); @@ -273,7 +273,7 @@ int exec_module(FAR struct binary_s *binp, #if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL) /* Restore the address environment of the caller */ - ret = addrenv_restore(); + ret = addrenv_restore(binp->oldenv); if (ret < 0) { berr("ERROR: addrenv_restore() failed: %d\n", ret); @@ -292,7 +292,7 @@ errout_with_tcbinit: errout_with_addrenv: #if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL) - addrenv_restore(); + addrenv_restore(binp->oldenv); errout_with_envp: #endif binfmt_freeenv(envp); diff --git a/binfmt/libelf/libelf_addrenv.c b/binfmt/libelf/libelf_addrenv.c index b437ca3c2bb..be737d28ecc 100644 --- a/binfmt/libelf/libelf_addrenv.c +++ b/binfmt/libelf/libelf_addrenv.c @@ -188,7 +188,7 @@ int elf_addrenv_select(FAR struct elf_loadinfo_s *loadinfo) /* Instantiate the new address environment */ - ret = addrenv_select(loadinfo->addrenv); + ret = addrenv_select(loadinfo->addrenv, &loadinfo->oldenv); if (ret < 0) { berr("ERROR: addrenv_select failed: %d\n", ret); @@ -240,7 +240,7 @@ int elf_addrenv_restore(FAR struct elf_loadinfo_s *loadinfo) /* Restore the old address environment */ - ret = addrenv_restore(); + ret = addrenv_restore(loadinfo->oldenv); if (ret < 0) { berr("ERROR: addrenv_restore failed: %d\n", ret); diff --git a/include/nuttx/addrenv.h b/include/nuttx/addrenv.h index afac66accc7..40d8c8f1105 100644 --- a/include/nuttx/addrenv.h +++ b/include/nuttx/addrenv.h @@ -390,7 +390,8 @@ int addrenv_leave(FAR struct tcb_s *tcb); * running process. * * Input Parameters: - * addrenv - The address environment. + * addrenv - The address environment to instantiate. + * oldenv - The old active address environment is placed here. * * Returned Value: * This is a NuttX internal function so it follows the convention that @@ -399,16 +400,17 @@ int addrenv_leave(FAR struct tcb_s *tcb); * ****************************************************************************/ -int addrenv_select(FAR struct addrenv_s *addrenv); +int addrenv_select(FAR struct addrenv_s *addrenv, + FAR struct addrenv_s **oldenv); /**************************************************************************** * Name: addrenv_restore * * Description: - * Switch back to the procces's own address environment. + * Switch back to the procces's previous address environment. * * Input Parameters: - * None + * addrenv - The address environment to restore. * * Returned Value: * This is a NuttX internal function so it follows the convention that @@ -417,7 +419,7 @@ int addrenv_select(FAR struct addrenv_s *addrenv); * ****************************************************************************/ -int addrenv_restore(void); +int addrenv_restore(FAR struct addrenv_s *addrenv); /**************************************************************************** * Name: addrenv_take diff --git a/include/nuttx/binfmt/binfmt.h b/include/nuttx/binfmt/binfmt.h index 6a1cac2589b..e1b8e18157c 100644 --- a/include/nuttx/binfmt/binfmt.h +++ b/include/nuttx/binfmt/binfmt.h @@ -87,6 +87,7 @@ struct binary_s */ FAR addrenv_t *addrenv; /* Address environment */ + FAR addrenv_t *oldenv; /* Saved address environment */ #endif size_t mapsize; /* Size of the mapped address region (needed for munmap) */ diff --git a/include/nuttx/binfmt/elf.h b/include/nuttx/binfmt/elf.h index 4fa595c1065..3e800e392eb 100644 --- a/include/nuttx/binfmt/elf.h +++ b/include/nuttx/binfmt/elf.h @@ -123,6 +123,7 @@ struct elf_loadinfo_s #ifdef CONFIG_ARCH_ADDRENV FAR addrenv_t *addrenv; /* Address environment */ + FAR addrenv_t *oldenv; /* Saved address environment */ #endif uint16_t symtabidx; /* Symbol table section index */ diff --git a/sched/addrenv/addrenv.c b/sched/addrenv/addrenv.c index 286512ab039..9bbb5b462a5 100644 --- a/sched/addrenv/addrenv.c +++ b/sched/addrenv/addrenv.c @@ -338,7 +338,8 @@ int addrenv_leave(FAR struct tcb_s *tcb) * running process. * * Input Parameters: - * addrenv - The address environment. + * addrenv - The address environment to instantiate. + * oldenv - The old active address environment is placed here. * * Returned Value: * This is a NuttX internal function so it follows the convention that @@ -347,10 +348,12 @@ int addrenv_leave(FAR struct tcb_s *tcb) * ****************************************************************************/ -int addrenv_select(FAR struct addrenv_s *addrenv) +int addrenv_select(FAR struct addrenv_s *addrenv, + FAR struct addrenv_s **oldenv) { FAR struct tcb_s *tcb = this_task(); addrenv_take(addrenv); + *oldenv = tcb->addrenv_curr; tcb->addrenv_curr = addrenv; return addrenv_switch(tcb); } @@ -359,10 +362,10 @@ int addrenv_select(FAR struct addrenv_s *addrenv) * Name: addrenv_restore * * Description: - * Switch back to the procces's own address environment. + * Switch back to the procces's previous address environment. * * Input Parameters: - * None + * addrenv - The address environment to restore. * * Returned Value: * This is a NuttX internal function so it follows the convention that @@ -371,11 +374,11 @@ int addrenv_select(FAR struct addrenv_s *addrenv) * ****************************************************************************/ -int addrenv_restore(void) +int addrenv_restore(FAR struct addrenv_s *addrenv) { FAR struct tcb_s *tcb = this_task(); addrenv_give(tcb->addrenv_curr); - tcb->addrenv_curr = tcb->addrenv_own; + tcb->addrenv_curr = addrenv; return addrenv_switch(tcb); } diff --git a/sched/group/group_argvstr.c b/sched/group/group_argvstr.c index 8de2aaaf6e5..d2a55577003 100644 --- a/sched/group/group_argvstr.c +++ b/sched/group/group_argvstr.c @@ -59,6 +59,9 @@ size_t group_argvstr(FAR struct tcb_s *tcb, FAR char *args, size_t size) { size_t n = 0; +#ifdef CONFIG_ARCH_ADDRENV + FAR struct addrenv_s *oldenv; +#endif /* Perform sanity checks */ @@ -73,7 +76,7 @@ size_t group_argvstr(FAR struct tcb_s *tcb, FAR char *args, size_t size) #ifdef CONFIG_ARCH_ADDRENV if (tcb->addrenv_own != NULL) { - addrenv_select(tcb->addrenv_own); + addrenv_select(tcb->addrenv_own, &oldenv); } #endif @@ -98,7 +101,7 @@ size_t group_argvstr(FAR struct tcb_s *tcb, FAR char *args, size_t size) #ifdef CONFIG_ARCH_ADDRENV if (tcb->addrenv_own != NULL) { - addrenv_restore(); + addrenv_restore(oldenv); } #endif diff --git a/sched/sched/sched_get_stateinfo.c b/sched/sched/sched_get_stateinfo.c index 10ae9180126..b2105431a16 100644 --- a/sched/sched/sched_get_stateinfo.c +++ b/sched/sched/sched_get_stateinfo.c @@ -83,6 +83,15 @@ void nxsched_get_stateinfo(FAR struct tcb_s *tcb, FAR char *state, { irqstate_t flags; +#ifdef CONFIG_ARCH_ADDRENV + FAR struct addrenv_s *oldenv; + + if (tcb->addrenv_own) + { + addrenv_select(tcb->addrenv_own, &oldenv); + } +#endif + /* if the state is waiting mutex */ flags = enter_critical_section(); @@ -100,4 +109,11 @@ void nxsched_get_stateinfo(FAR struct tcb_s *tcb, FAR char *state, leave_critical_section(flags); strlcpy(state, g_statenames[tcb->task_state], length); } + +#ifdef CONFIG_ARCH_ADDRENV + if (tcb->addrenv_own) + { + addrenv_restore(oldenv); + } +#endif } diff --git a/sched/semaphore/sem_waitirq.c b/sched/semaphore/sem_waitirq.c index 7d690290109..8875ce0b7d0 100644 --- a/sched/semaphore/sem_waitirq.c +++ b/sched/semaphore/sem_waitirq.c @@ -73,9 +73,11 @@ void nxsem_wait_irq(FAR struct tcb_s *wtcb, int errcode) FAR sem_t *sem = wtcb->waitobj; #ifdef CONFIG_ARCH_ADDRENV + FAR struct addrenv_s *oldenv; + if (wtcb->addrenv_own) { - addrenv_select(wtcb->addrenv_own); + addrenv_select(wtcb->addrenv_own, &oldenv); } #endif @@ -106,7 +108,7 @@ void nxsem_wait_irq(FAR struct tcb_s *wtcb, int errcode) #ifdef CONFIG_ARCH_ADDRENV if (wtcb->addrenv_own) { - addrenv_restore(); + addrenv_restore(oldenv); } #endif