sched/addrenv.c: Implement re-entrancy for addrenv_select()

Store the old environment in a local context so another temporary address
environment can be selected. This can happen especially when a process
is being loaded (the new process's mappings are temporarily instantiated)
and and interrupt occurs.
This commit is contained in:
Ville Juven 2023-04-19 15:29:00 +03:00 committed by Alin Jerpelea
parent 20623d7369
commit d48114a4b7
11 changed files with 56 additions and 24 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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) */

View File

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

View File

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

View File

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

View File

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

View File

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