Skip to content

Commit d48114a

Browse files
pussuwjerpelea
authored andcommitted
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.
1 parent 20623d7 commit d48114a

File tree

11 files changed

+56
-24
lines changed

11 files changed

+56
-24
lines changed

arch/arm/src/common/arm_checkstack.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,9 +203,11 @@ size_t up_check_tcbstack(struct tcb_s *tcb)
203203
size_t size;
204204

205205
#ifdef CONFIG_ARCH_ADDRENV
206+
FAR struct addrenv_s *oldenv;
207+
206208
if (tcb->addrenv_own != NULL)
207209
{
208-
addrenv_select(tcb->addrenv_own);
210+
addrenv_select(tcb->addrenv_own, &oldenv);
209211
}
210212
#endif
211213

@@ -214,7 +216,7 @@ size_t up_check_tcbstack(struct tcb_s *tcb)
214216
#ifdef CONFIG_ARCH_ADDRENV
215217
if (tcb->addrenv_own != NULL)
216218
{
217-
addrenv_restore();
219+
addrenv_restore(oldenv);
218220
}
219221
#endif
220222

arch/risc-v/src/common/riscv_checkstack.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,11 @@ size_t up_check_tcbstack(struct tcb_s *tcb)
159159
size_t size;
160160

161161
#ifdef CONFIG_ARCH_ADDRENV
162+
FAR struct addrenv_s *oldenv;
163+
162164
if (tcb->addrenv_own != NULL)
163165
{
164-
addrenv_select(tcb->addrenv_own);
166+
addrenv_select(tcb->addrenv_own, &oldenv);
165167
}
166168
#endif
167169

@@ -171,7 +173,7 @@ size_t up_check_tcbstack(struct tcb_s *tcb)
171173
#ifdef CONFIG_ARCH_ADDRENV
172174
if (tcb->addrenv_own != NULL)
173175
{
174-
addrenv_restore();
176+
addrenv_restore(oldenv);
175177
}
176178
#endif
177179

binfmt/binfmt_execmodule.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ int exec_module(FAR struct binary_s *binp,
165165
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL)
166166
/* Instantiate the address environment containing the user heap */
167167

168-
ret = addrenv_select(binp->addrenv);
168+
ret = addrenv_select(binp->addrenv, &binp->oldenv);
169169
if (ret < 0)
170170
{
171171
berr("ERROR: addrenv_select() failed: %d\n", ret);
@@ -273,7 +273,7 @@ int exec_module(FAR struct binary_s *binp,
273273
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL)
274274
/* Restore the address environment of the caller */
275275

276-
ret = addrenv_restore();
276+
ret = addrenv_restore(binp->oldenv);
277277
if (ret < 0)
278278
{
279279
berr("ERROR: addrenv_restore() failed: %d\n", ret);
@@ -292,7 +292,7 @@ int exec_module(FAR struct binary_s *binp,
292292

293293
errout_with_addrenv:
294294
#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL)
295-
addrenv_restore();
295+
addrenv_restore(binp->oldenv);
296296
errout_with_envp:
297297
#endif
298298
binfmt_freeenv(envp);

binfmt/libelf/libelf_addrenv.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ int elf_addrenv_select(FAR struct elf_loadinfo_s *loadinfo)
188188

189189
/* Instantiate the new address environment */
190190

191-
ret = addrenv_select(loadinfo->addrenv);
191+
ret = addrenv_select(loadinfo->addrenv, &loadinfo->oldenv);
192192
if (ret < 0)
193193
{
194194
berr("ERROR: addrenv_select failed: %d\n", ret);
@@ -240,7 +240,7 @@ int elf_addrenv_restore(FAR struct elf_loadinfo_s *loadinfo)
240240

241241
/* Restore the old address environment */
242242

243-
ret = addrenv_restore();
243+
ret = addrenv_restore(loadinfo->oldenv);
244244
if (ret < 0)
245245
{
246246
berr("ERROR: addrenv_restore failed: %d\n", ret);

include/nuttx/addrenv.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,8 @@ int addrenv_leave(FAR struct tcb_s *tcb);
390390
* running process.
391391
*
392392
* Input Parameters:
393-
* addrenv - The address environment.
393+
* addrenv - The address environment to instantiate.
394+
* oldenv - The old active address environment is placed here.
394395
*
395396
* Returned Value:
396397
* This is a NuttX internal function so it follows the convention that
@@ -399,16 +400,17 @@ int addrenv_leave(FAR struct tcb_s *tcb);
399400
*
400401
****************************************************************************/
401402

402-
int addrenv_select(FAR struct addrenv_s *addrenv);
403+
int addrenv_select(FAR struct addrenv_s *addrenv,
404+
FAR struct addrenv_s **oldenv);
403405

404406
/****************************************************************************
405407
* Name: addrenv_restore
406408
*
407409
* Description:
408-
* Switch back to the procces's own address environment.
410+
* Switch back to the procces's previous address environment.
409411
*
410412
* Input Parameters:
411-
* None
413+
* addrenv - The address environment to restore.
412414
*
413415
* Returned Value:
414416
* This is a NuttX internal function so it follows the convention that
@@ -417,7 +419,7 @@ int addrenv_select(FAR struct addrenv_s *addrenv);
417419
*
418420
****************************************************************************/
419421

420-
int addrenv_restore(void);
422+
int addrenv_restore(FAR struct addrenv_s *addrenv);
421423

422424
/****************************************************************************
423425
* Name: addrenv_take

include/nuttx/binfmt/binfmt.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ struct binary_s
8787
*/
8888

8989
FAR addrenv_t *addrenv; /* Address environment */
90+
FAR addrenv_t *oldenv; /* Saved address environment */
9091
#endif
9192

9293
size_t mapsize; /* Size of the mapped address region (needed for munmap) */

include/nuttx/binfmt/elf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ struct elf_loadinfo_s
123123

124124
#ifdef CONFIG_ARCH_ADDRENV
125125
FAR addrenv_t *addrenv; /* Address environment */
126+
FAR addrenv_t *oldenv; /* Saved address environment */
126127
#endif
127128

128129
uint16_t symtabidx; /* Symbol table section index */

sched/addrenv/addrenv.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,8 @@ int addrenv_leave(FAR struct tcb_s *tcb)
338338
* running process.
339339
*
340340
* Input Parameters:
341-
* addrenv - The address environment.
341+
* addrenv - The address environment to instantiate.
342+
* oldenv - The old active address environment is placed here.
342343
*
343344
* Returned Value:
344345
* This is a NuttX internal function so it follows the convention that
@@ -347,10 +348,12 @@ int addrenv_leave(FAR struct tcb_s *tcb)
347348
*
348349
****************************************************************************/
349350

350-
int addrenv_select(FAR struct addrenv_s *addrenv)
351+
int addrenv_select(FAR struct addrenv_s *addrenv,
352+
FAR struct addrenv_s **oldenv)
351353
{
352354
FAR struct tcb_s *tcb = this_task();
353355
addrenv_take(addrenv);
356+
*oldenv = tcb->addrenv_curr;
354357
tcb->addrenv_curr = addrenv;
355358
return addrenv_switch(tcb);
356359
}
@@ -359,10 +362,10 @@ int addrenv_select(FAR struct addrenv_s *addrenv)
359362
* Name: addrenv_restore
360363
*
361364
* Description:
362-
* Switch back to the procces's own address environment.
365+
* Switch back to the procces's previous address environment.
363366
*
364367
* Input Parameters:
365-
* None
368+
* addrenv - The address environment to restore.
366369
*
367370
* Returned Value:
368371
* This is a NuttX internal function so it follows the convention that
@@ -371,11 +374,11 @@ int addrenv_select(FAR struct addrenv_s *addrenv)
371374
*
372375
****************************************************************************/
373376

374-
int addrenv_restore(void)
377+
int addrenv_restore(FAR struct addrenv_s *addrenv)
375378
{
376379
FAR struct tcb_s *tcb = this_task();
377380
addrenv_give(tcb->addrenv_curr);
378-
tcb->addrenv_curr = tcb->addrenv_own;
381+
tcb->addrenv_curr = addrenv;
379382
return addrenv_switch(tcb);
380383
}
381384

sched/group/group_argvstr.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@
5959
size_t group_argvstr(FAR struct tcb_s *tcb, FAR char *args, size_t size)
6060
{
6161
size_t n = 0;
62+
#ifdef CONFIG_ARCH_ADDRENV
63+
FAR struct addrenv_s *oldenv;
64+
#endif
6265

6366
/* Perform sanity checks */
6467

@@ -73,7 +76,7 @@ size_t group_argvstr(FAR struct tcb_s *tcb, FAR char *args, size_t size)
7376
#ifdef CONFIG_ARCH_ADDRENV
7477
if (tcb->addrenv_own != NULL)
7578
{
76-
addrenv_select(tcb->addrenv_own);
79+
addrenv_select(tcb->addrenv_own, &oldenv);
7780
}
7881
#endif
7982

@@ -98,7 +101,7 @@ size_t group_argvstr(FAR struct tcb_s *tcb, FAR char *args, size_t size)
98101
#ifdef CONFIG_ARCH_ADDRENV
99102
if (tcb->addrenv_own != NULL)
100103
{
101-
addrenv_restore();
104+
addrenv_restore(oldenv);
102105
}
103106
#endif
104107

sched/sched/sched_get_stateinfo.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,15 @@ void nxsched_get_stateinfo(FAR struct tcb_s *tcb, FAR char *state,
8383
{
8484
irqstate_t flags;
8585

86+
#ifdef CONFIG_ARCH_ADDRENV
87+
FAR struct addrenv_s *oldenv;
88+
89+
if (tcb->addrenv_own)
90+
{
91+
addrenv_select(tcb->addrenv_own, &oldenv);
92+
}
93+
#endif
94+
8695
/* if the state is waiting mutex */
8796

8897
flags = enter_critical_section();
@@ -100,4 +109,11 @@ void nxsched_get_stateinfo(FAR struct tcb_s *tcb, FAR char *state,
100109
leave_critical_section(flags);
101110
strlcpy(state, g_statenames[tcb->task_state], length);
102111
}
112+
113+
#ifdef CONFIG_ARCH_ADDRENV
114+
if (tcb->addrenv_own)
115+
{
116+
addrenv_restore(oldenv);
117+
}
118+
#endif
103119
}

0 commit comments

Comments
 (0)