This is an automated email from the ASF dual-hosted git repository. acassis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 2f06af7d5d7e9eb6c0ca34379bbb3bbdad075f51 Author: Marco Casaroli <[email protected]> AuthorDate: Mon Oct 12 10:20:39 2026 +0200 sched/addrenv: Drop the old address environment after the lock. addrenv_switch() dropped the reference to the old address environment while it held g_addrenv_lock. When that was the last reference, addrenv_drop() queued the destruction on the work queue, and work_queue() enters the critical section. With SMP, another CPU could hold the critical section during a context switch and wait for g_addrenv_lock in addrenv_switch(): both CPUs then spun for ever. Drop the reference after the lock is released. The old address environment is no longer installed on this CPU at that point. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marco Casaroli <[email protected]> --- sched/addrenv/addrenv.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/sched/addrenv/addrenv.c b/sched/addrenv/addrenv.c index 8c768336ea7..66afa48dcda 100644 --- a/sched/addrenv/addrenv.c +++ b/sched/addrenv/addrenv.c @@ -125,6 +125,7 @@ static void addrenv_destroy(FAR void *arg) int addrenv_switch(FAR struct tcb_s *tcb) { + FAR struct addrenv_s *drop = NULL; FAR struct addrenv_s *curr; FAR struct addrenv_s *next; irqstate_t flags; @@ -180,12 +181,9 @@ int addrenv_switch(FAR struct tcb_s *tcb) berr("ERROR: up_addrenv_select failed: %d\n", ret); } - /* This is a safe spot to drop the current address environment */ + /* The current address environment is dropped below */ - if (curr) - { - addrenv_drop(curr, true); - } + drop = curr; /* Save the new, current address environment group */ @@ -193,6 +191,13 @@ int addrenv_switch(FAR struct tcb_s *tcb) } spin_unlock_irqrestore_nopreempt(&g_addrenv_lock, flags); + + /* Drop the old address environment after the lock is released: + * addrenv_drop() may queue work, which enters the critical section. + * Another CPU can hold the critical section and wait for this lock. + */ + + addrenv_drop(drop, true); return OK; }
