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:
parent
20623d7369
commit
d48114a4b7
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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) */
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user