mirror of
https://github.com/apache/nuttx.git
synced 2026-05-31 05:55:46 +08:00
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:
committed by
Alin Jerpelea
parent
20623d7369
commit
d48114a4b7
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user