Removed FIFO queueing from the ARMv7-A SMP ports so an ISR can no longer deadlock waiting for protection (#707)

The Cortex-A5, A7 and A9 SMP ports guarded the inter-core protection with
a FIFO wait list: a core that could not take the lock added itself to a
queue, incremented _tx_thread_smp_protect_wait_counts[core], and only the
core at the head of the queue was allowed to acquire.

Two parts of that scheme require the waiting core to be interruptible.
_tx_thread_smp_unprotect() refuses to release the protection while the
releasing core's own wait count is non-zero, and a queued core is taken
back out of the list by _tx_thread_context_restore() when it is preempted.
Neither can happen on a core that is spinning inside an ISR with
interrupts already masked, because the spin loop restores the caller's
interrupt posture rather than enabling interrupts. The core stays in the
list forever and the system deadlocks with cores stuck in the wait loop.

This is the deadlock Microsoft removed from the ARMv8-A SMP ports in
6.1.11, by dropping the wait list and using a plain LDAXR/STXR spinlock.
The same removal was announced for the ARMv7-A ports at the time but was
never made, so those three ports have carried the deadlock ever since.

The FIFO queueing is now removed from the ARMv7-A SMP ports as well.
_tx_thread_smp_protect() becomes an LDREX/STREX spinlock that releases
interrupts between attempts, matching the sequence already used by the
Cortex-R8 SMP port; _tx_thread_smp_unprotect() no longer consults the
wait counts; and _tx_thread_context_restore() no longer has to unqueue a
preempted core. The now unreferenced wait list macro headers are deleted.

Verified by assembling all three GNU ports with arm-none-eabi-gcc for
cortex-a5, cortex-a7 and cortex-a9, with and without
TX_ENABLE_FIQ_SUPPORT, TX_ENABLE_WFE and TX_MPCORE_DEBUG_ENABLE, and by
reading back the disassembly of the new protect sequence. The port
consistency checks pass.

Fixes #219

Assisted-by: Copilot (Opus 5) <noreply@github.com>
This commit is contained in:
Frédéric Desbiens
2026-09-09 10:29:51 -04:00
committed by GitHub
parent d3fb72b6dd
commit 37f48fa83c
24 changed files with 400 additions and 3825 deletions
@@ -1,5 +1,6 @@
;/***************************************************************************
; * Copyright (c) 2024 Microsoft Corporation
; * Copyright (c) 2026 Eclipse ThreadX contributors
; *
; * This program and the accompanying materials are made available under the
; * terms of the MIT License which is available at
@@ -7,6 +8,7 @@
; *
; * SPDX-License-Identifier: MIT
; **************************************************************************/
; Some portions generated by Copilot (Opus 5).
;
;
;/**************************************************************************/
@@ -29,8 +31,6 @@
;#include "tx_thread.h"
;#include "tx_timer.h"
;
;/* Include macros for modifying the wait list. */
#include "tx_thread_smp_protection_wait_list_macros.h"
IF :DEF:TX_ENABLE_FIQ_SUPPORT
DISABLE_INTS EQU 0xC0 ; Disable IRQ & FIQ interrupts
@@ -51,11 +51,6 @@ SVC_MODE EQU 0x93 ; SVC mode
IMPORT _tx_thread_preempt_disable
IMPORT _tx_timer_interrupt_active
IMPORT _tx_thread_smp_protection
IMPORT _tx_thread_smp_protect_wait_counts
IMPORT _tx_thread_smp_protect_wait_list
IMPORT _tx_thread_smp_protect_wait_list_lock_protect_in_force
IMPORT _tx_thread_smp_protect_wait_list_tail
IMPORT _tx_thread_smp_protect_wait_list_size
IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY
IMPORT _tx_execution_isr_exit
ENDIF
@@ -196,77 +191,6 @@ __tx_thread_no_preempt_restore
; {
;
__tx_thread_preempt_restore
;
; /* Was the thread being preempted waiting for the lock? */
; if (_tx_thread_smp_protect_wait_counts[this_core] != 0)
; {
;
LDR r1, =_tx_thread_smp_protect_wait_counts ; Load waiting count list
LDR r2, [r1, r10, LSL #2] ; Load waiting value for this core
CMP r2, #0
BEQ _nobody_waiting_for_lock ; Is the core waiting for the lock?
;
; /* Do we not have the lock? This means the ISR never got the inter-core lock. */
; if (_tx_thread_smp_protection.tx_thread_smp_protect_owned != this_core)
; {
;
LDR r1, =_tx_thread_smp_protection ; Load address of protection structure
LDR r2, [r1, #8] ; Pickup the owning core
CMP r10, r2 ; Compare our core to the owning core
BEQ _this_core_has_lock ; Do we have the lock?
;
; /* We don't have the lock. This core should be in the list. Remove it. */
; _tx_thread_smp_protect_wait_list_remove(this_core);
;
MOV r0, r10 ; Move the core ID to r0 for the macro
macro_call0 _tx_thread_smp_protect_wait_list_remove ; Call macro to remove core from the list
B _nobody_waiting_for_lock ; Leave
;
; }
; else
; {
; /* We have the lock. This means the ISR got the inter-core lock, but
; never released it because it saw that there was someone waiting.
; Note this core is not in the list. */
;
_this_core_has_lock
;
; /* We're no longer waiting. Note that this should be zero since this happens during thread preemption. */
; _tx_thread_smp_protect_wait_counts[core]--;
;
LDR r1, =_tx_thread_smp_protect_wait_counts ; Load waiting count list
LDR r2, [r1, r10, LSL #2] ; Load waiting value for this core
SUB r2, r2, #1 ; Decrement waiting value. Should be zero now
STR r2, [r1, r10, LSL #2] ; Store new waiting value
;
; /* Now release the inter-core lock. */
;
; /* Set protected core as invalid. */
; _tx_thread_smp_protection.tx_thread_smp_protect_core = 0xFFFFFFFF;
;
LDR r1, =_tx_thread_smp_protection ; Load address of protection structure
MOV r2, #0xFFFFFFFF ; Build invalid value
STR r2, [r1, #8] ; Mark the protected core as invalid
DMB ; Ensure that accesses to shared resource have completed
;
; /* Release protection. */
; _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 0;
;
MOV r2, #0 ; Build release protection value
STR r2, [r1, #0] ; Release the protection
DSB ISH ; To ensure update of the protection occurs before other CPUs awake
;
; /* Wake up waiting processors. Note interrupts are already enabled. */
;
IF :DEF:TX_ENABLE_WFE
SEV ; Send event to other CPUs
ENDIF
;
; }
; }
;
_nobody_waiting_for_lock
LDMIA sp!, {r3, r10, r12, lr} ; Recover temporarily saved registers
MOV r1, lr ; Save lr (point of interrupt)
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,5 +1,6 @@
;/***************************************************************************
; * Copyright (c) 2024 Microsoft Corporation
; * Copyright (c) 2026 Eclipse ThreadX contributors
; *
; * This program and the accompanying materials are made available under the
; * terms of the MIT License which is available at
@@ -7,6 +8,7 @@
; *
; * SPDX-License-Identifier: MIT
; **************************************************************************/
; Some portions generated by Copilot (Opus 5).
;
;
;/**************************************************************************/
@@ -33,7 +35,6 @@
IMPORT _tx_thread_current_ptr
IMPORT _tx_thread_smp_protection
IMPORT _tx_thread_preempt_disable
IMPORT _tx_thread_smp_protect_wait_counts
AREA ||.text||, CODE, READONLY
PRESERVE8
@@ -103,10 +104,6 @@ _tx_thread_smp_unprotect
CMP r3, #0 ; Is the preempt disable flag set?
BNE _still_protected ; Yes, skip the protection release
LDR r2,=_tx_thread_smp_protect_wait_counts ; Build build address of wait counts
LDR r3, [r2, r1, LSL #2] ; Pickup wait list value
CMP r3, #0 ; Are any entities on this core waiting?
BNE _still_protected ; Yes, skip the protection release
LDR r2,=_tx_thread_smp_protection ; Build address of protection structure
MOV r3, #0xFFFFFFFF ; Build invalid value
@@ -1,5 +1,6 @@
@/***************************************************************************
@ * Copyright (c) 2024 Microsoft Corporation
@ * Copyright (c) 2026 Eclipse ThreadX contributors
@ *
@ * This program and the accompanying materials are made available under the
@ * terms of the MIT License which is available at
@@ -7,6 +8,7 @@
@ *
@ * SPDX-License-Identifier: MIT
@ **************************************************************************/
@ Some portions generated by Copilot (Opus 5).
@
@
@/**************************************************************************/
@@ -29,8 +31,6 @@
@#include "tx_thread.h"
@#include "tx_timer.h"
@
@/* Include macros for modifying the wait list. */
#include "tx_thread_smp_protection_wait_list_macros.h"
#ifdef TX_ENABLE_FIQ_SUPPORT
DISABLE_INTS = 0xC0 @ Disable IRQ & FIQ interrupts
@@ -51,11 +51,6 @@ SVC_MODE = 0x93 @ SVC mode
.global _tx_thread_preempt_disable
.global _tx_timer_interrupt_active
.global _tx_thread_smp_protection
.global _tx_thread_smp_protect_wait_counts
.global _tx_thread_smp_protect_wait_list
.global _tx_thread_smp_protect_wait_list_lock_protect_in_force
.global _tx_thread_smp_protect_wait_list_tail
.global _tx_thread_smp_protect_wait_list_size
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
.global _tx_execution_isr_exit
#endif
@@ -198,77 +193,6 @@ __tx_thread_no_preempt_restore:
@ {
@
__tx_thread_preempt_restore:
@
@ /* Was the thread being preempted waiting for the lock? */
@ if (_tx_thread_smp_protect_wait_counts[this_core] != 0)
@ {
@
LDR r1, =_tx_thread_smp_protect_wait_counts @ Load waiting count list
LDR r2, [r1, r10, LSL #2] @ Load waiting value for this core
CMP r2, #0
BEQ _nobody_waiting_for_lock @ Is the core waiting for the lock?
@
@ /* Do we not have the lock? This means the ISR never got the inter-core lock. */
@ if (_tx_thread_smp_protection.tx_thread_smp_protect_owned != this_core)
@ {
@
LDR r1, =_tx_thread_smp_protection @ Load address of protection structure
LDR r2, [r1, #8] @ Pickup the owning core
CMP r10, r2 @ Compare our core to the owning core
BEQ _this_core_has_lock @ Do we have the lock?
@
@ /* We don't have the lock. This core should be in the list. Remove it. */
@ _tx_thread_smp_protect_wait_list_remove(this_core);
@
MOV r0, r10 @ Move the core ID to r0 for the macro
_tx_thread_smp_protect_wait_list_remove @ Call macro to remove core from the list
B _nobody_waiting_for_lock @ Leave
@
@ }
@ else
@ {
@ /* We have the lock. This means the ISR got the inter-core lock, but
@ never released it because it saw that there was someone waiting.
@ Note this core is not in the list. */
@
_this_core_has_lock:
@
@ /* We're no longer waiting. Note that this should be zero since this happens during thread preemption. */
@ _tx_thread_smp_protect_wait_counts[core]--;
@
LDR r1, =_tx_thread_smp_protect_wait_counts @ Load waiting count list
LDR r2, [r1, r10, LSL #2] @ Load waiting value for this core
SUB r2, r2, #1 @ Decrement waiting value. Should be zero now
STR r2, [r1, r10, LSL #2] @ Store new waiting value
@
@ /* Now release the inter-core lock. */
@
@ /* Set protected core as invalid. */
@ _tx_thread_smp_protection.tx_thread_smp_protect_core = 0xFFFFFFFF;
@
LDR r1, =_tx_thread_smp_protection @ Load address of protection structure
MOV r2, #0xFFFFFFFF @ Build invalid value
STR r2, [r1, #8] @ Mark the protected core as invalid
DMB @ Ensure that accesses to shared resource have completed
@
@ /* Release protection. */
@ _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 0;
@
MOV r2, #0 @ Build release protection value
STR r2, [r1, #0] @ Release the protection
DSB ISH @ To ensure update of the protection occurs before other CPUs awake
@
@ /* Wake up waiting processors. Note interrupts are already enabled. */
@
#ifdef TX_ENABLE_WFE
SEV @ Send event to other CPUs
#endif
@
@ }
@ }
@
_nobody_waiting_for_lock:
LDMIA sp!, {r3, r10, r12, lr} @ Recover temporarily saved registers
MOV r1, lr @ Save lr (point of interrupt)
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,5 +1,6 @@
@/***************************************************************************
@ * Copyright (c) 2024 Microsoft Corporation
@ * Copyright (c) 2026 Eclipse ThreadX contributors
@ *
@ * This program and the accompanying materials are made available under the
@ * terms of the MIT License which is available at
@@ -7,6 +8,7 @@
@ *
@ * SPDX-License-Identifier: MIT
@ **************************************************************************/
@ Some portions generated by Copilot (Opus 5).
@
@
@/**************************************************************************/
@@ -33,7 +35,6 @@
.global _tx_thread_current_ptr
.global _tx_thread_smp_protection
.global _tx_thread_preempt_disable
.global _tx_thread_smp_protect_wait_counts
.arm
.text
@@ -105,10 +106,6 @@ _tx_thread_smp_unprotect:
CMP r3, #0 @ Is the preempt disable flag set?
BNE _still_protected @ Yes, skip the protection release
LDR r2,=_tx_thread_smp_protect_wait_counts @ Build build address of wait counts
LDR r3, [r2, r1, LSL #2] @ Pickup wait list value
CMP r3, #0 @ Are any entities on this core waiting?
BNE _still_protected @ Yes, skip the protection release
LDR r2,=_tx_thread_smp_protection @ Build address of protection structure
MOV r3, #0xFFFFFFFF @ Build invalid value
@@ -1,5 +1,6 @@
;/***************************************************************************
; * Copyright (c) 2024 Microsoft Corporation
; * Copyright (c) 2026 Eclipse ThreadX contributors
; *
; * This program and the accompanying materials are made available under the
; * terms of the MIT License which is available at
@@ -7,6 +8,7 @@
; *
; * SPDX-License-Identifier: MIT
; **************************************************************************/
; Some portions generated by Copilot (Opus 5).
;
;
;/**************************************************************************/
@@ -29,8 +31,6 @@
;#include "tx_thread.h"
;#include "tx_timer.h"
;
;/* Include macros for modifying the wait list. */
#include "tx_thread_smp_protection_wait_list_macros.h"
IF :DEF:TX_ENABLE_FIQ_SUPPORT
DISABLE_INTS EQU 0xC0 ; Disable IRQ & FIQ interrupts
@@ -51,11 +51,6 @@ SVC_MODE EQU 0x93 ; SVC mode
IMPORT _tx_thread_preempt_disable
IMPORT _tx_timer_interrupt_active
IMPORT _tx_thread_smp_protection
IMPORT _tx_thread_smp_protect_wait_counts
IMPORT _tx_thread_smp_protect_wait_list
IMPORT _tx_thread_smp_protect_wait_list_lock_protect_in_force
IMPORT _tx_thread_smp_protect_wait_list_tail
IMPORT _tx_thread_smp_protect_wait_list_size
IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY
IMPORT _tx_execution_isr_exit
ENDIF
@@ -195,76 +190,6 @@ __tx_thread_no_preempt_restore
; else
; {
__tx_thread_preempt_restore
;
; /* Was the thread being preempted waiting for the lock? */
; if (_tx_thread_smp_protect_wait_counts[this_core] != 0)
; {
;
LDR r1, =_tx_thread_smp_protect_wait_counts ; Load waiting count list
LDR r2, [r1, r10, LSL #2] ; Load waiting value for this core
CMP r2, #0
BEQ _nobody_waiting_for_lock ; Is the core waiting for the lock?
;
; /* Do we not have the lock? This means the ISR never got the inter-core lock. */
; if (_tx_thread_smp_protection.tx_thread_smp_protect_owned != this_core)
; {
;
LDR r1, =_tx_thread_smp_protection ; Load address of protection structure
LDR r2, [r1, #8] ; Pickup the owning core
CMP r10, r2 ; Compare our core to the owning core
BEQ _this_core_has_lock ; Do we have the lock?
;
; /* We don't have the lock. This core should be in the list. Remove it. */
; _tx_thread_smp_protect_wait_list_remove(this_core);
;
macro_call0 _tx_thread_smp_protect_wait_list_remove ; Call macro to remove core from the list
B _nobody_waiting_for_lock ; Leave
;
; }
; else
; {
; /* We have the lock. This means the ISR got the inter-core lock, but
; never released it because it saw that there was someone waiting.
; Note this core is not in the list. */
;
_this_core_has_lock
;
; /* We're no longer waiting. Note that this should be zero since this happens during thread preemption. */
; _tx_thread_smp_protect_wait_counts[core]--;
;
LDR r1, =_tx_thread_smp_protect_wait_counts ; Load waiting count list
LDR r2, [r1, r10, LSL #2] ; Load waiting value for this core
SUB r2, r2, #1 ; Decrement waiting value. Should be zero now
STR r2, [r1, r10, LSL #2] ; Store new waiting value
;
; /* Now release the inter-core lock. */
;
; /* Set protected core as invalid. */
; _tx_thread_smp_protection.tx_thread_smp_protect_core = 0xFFFFFFFF;
;
LDR r1, =_tx_thread_smp_protection ; Load address of protection structure
MOV r2, #0xFFFFFFFF ; Build invalid value
STR r2, [r1, #8] ; Mark the protected core as invalid
DMB ; Ensure that accesses to shared resource have completed
;
; /* Release protection. */
; _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 0;
;
MOV r2, #0 ; Build release protection value
STR r2, [r1, #0] ; Release the protection
DSB ISH ; To ensure update of the protection occurs before other CPUs awake
;
; /* Wake up waiting processors. Note interrupts are already enabled. */
;
IF :DEF:TX_ENABLE_WFE
SEV ; Send event to other CPUs
ENDIF
;
; }
; }
;
_nobody_waiting_for_lock
LDMIA sp!, {r3, r10, r12, lr} ; Recover temporarily saved registers
MOV r1, lr ; Save lr (point of interrupt)
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,5 +1,6 @@
;/***************************************************************************
; * Copyright (c) 2024 Microsoft Corporation
; * Copyright (c) 2026 Eclipse ThreadX contributors
; *
; * This program and the accompanying materials are made available under the
; * terms of the MIT License which is available at
@@ -7,6 +8,7 @@
; *
; * SPDX-License-Identifier: MIT
; **************************************************************************/
; Some portions generated by Copilot (Opus 5).
;
;
;/**************************************************************************/
@@ -33,7 +35,6 @@
IMPORT _tx_thread_current_ptr
IMPORT _tx_thread_smp_protection
IMPORT _tx_thread_preempt_disable
IMPORT _tx_thread_smp_protect_wait_counts
AREA ||.text||, CODE, READONLY
PRESERVE8
@@ -103,10 +104,6 @@ _tx_thread_smp_unprotect
CMP r3, #0 ; Is the preempt disable flag set?
BNE _still_protected ; Yes, skip the protection release
LDR r2,=_tx_thread_smp_protect_wait_counts ; Build build address of wait counts
LDR r3, [r2, r1, LSL #2] ; Pickup wait list value
CMP r3, #0 ; Are any entities on this core waiting?
BNE _still_protected ; Yes, skip the protection release
LDR r2,=_tx_thread_smp_protection ; Build address of protection structure
MOV r3, #0xFFFFFFFF ; Build invalid value
@@ -1,5 +1,6 @@
@/***************************************************************************
@ * Copyright (c) 2024 Microsoft Corporation
@ * Copyright (c) 2026 Eclipse ThreadX contributors
@ *
@ * This program and the accompanying materials are made available under the
@ * terms of the MIT License which is available at
@@ -7,6 +8,7 @@
@ *
@ * SPDX-License-Identifier: MIT
@ **************************************************************************/
@ Some portions generated by Copilot (Opus 5).
@
@
@/**************************************************************************/
@@ -28,8 +30,6 @@
@#include "tx_api.h"
@#include "tx_thread.h"
@#include "tx_timer.h"
@/* Include macros for modifying the wait list. */
#include "tx_thread_smp_protection_wait_list_macros.h"
.arm
@@ -50,11 +50,6 @@ IRQ_MODE = 0x92 @ Disable IRQ, IRQ mode
.global _tx_thread_preempt_disable
.global _tx_timer_interrupt_active
.global _tx_thread_smp_protection
.global _tx_thread_smp_protect_wait_counts
.global _tx_thread_smp_protect_wait_list
.global _tx_thread_smp_protect_wait_list_lock_protect_in_force
.global _tx_thread_smp_protect_wait_list_tail
.global _tx_thread_smp_protect_wait_list_size
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
.global _tx_execution_isr_exit
#endif
@@ -200,76 +195,6 @@ __tx_thread_no_preempt_restore:
@ else
@ {
__tx_thread_preempt_restore:
@
@ /* Was the thread being preempted waiting for the lock? */
@ if (_tx_thread_smp_protect_wait_counts[this_core] != 0)
@ {
@
LDR r1, =_tx_thread_smp_protect_wait_counts @ Load waiting count list
LDR r2, [r1, r10, LSL #2] @ Load waiting value for this core
CMP r2, #0
BEQ _nobody_waiting_for_lock @ Is the core waiting for the lock?
@
@ /* Do we not have the lock? This means the ISR never got the inter-core lock. */
@ if (_tx_thread_smp_protection.tx_thread_smp_protect_owned != this_core)
@ {
@
LDR r1, =_tx_thread_smp_protection @ Load address of protection structure
LDR r2, [r1, #8] @ Pickup the owning core
CMP r10, r2 @ Compare our core to the owning core
BEQ _this_core_has_lock @ Do we have the lock?
@
@ /* We don't have the lock. This core should be in the list. Remove it. */
@ _tx_thread_smp_protect_wait_list_remove(this_core);
@
_tx_thread_smp_protect_wait_list_remove @ Call macro to remove core from the list
B _nobody_waiting_for_lock @ Leave
@
@ }
@ else
@ {
@ /* We have the lock. This means the ISR got the inter-core lock, but
@ never released it because it saw that there was someone waiting.
@ Note this core is not in the list. */
@
_this_core_has_lock:
@
@ /* We're no longer waiting. Note that this should be zero since this happens during thread preemption. */
@ _tx_thread_smp_protect_wait_counts[core]--;
@
LDR r1, =_tx_thread_smp_protect_wait_counts @ Load waiting count list
LDR r2, [r1, r10, LSL #2] @ Load waiting value for this core
SUB r2, r2, #1 @ Decrement waiting value. Should be zero now
STR r2, [r1, r10, LSL #2] @ Store new waiting value
@
@ /* Now release the inter-core lock. */
@
@ /* Set protected core as invalid. */
@ _tx_thread_smp_protection.tx_thread_smp_protect_core = 0xFFFFFFFF;
@
LDR r1, =_tx_thread_smp_protection @ Load address of protection structure
MOV r2, #0xFFFFFFFF @ Build invalid value
STR r2, [r1, #8] @ Mark the protected core as invalid
DMB @ Ensure that accesses to shared resource have completed
@
@ /* Release protection. */
@ _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 0;
@
MOV r2, #0 @ Build release protection value
STR r2, [r1, #0] @ Release the protection
DSB ISH @ To ensure update of the protection occurs before other CPUs awake
@
@ /* Wake up waiting processors. Note interrupts are already enabled. */
@
#ifdef TX_ENABLE_WFE
SEV @ Send event to other CPUs
#endif
@
@ }
@ }
@
_nobody_waiting_for_lock:
LDMIA sp!, {r3, r10, r12, lr} @ Recover temporarily saved registers
MOV r1, lr @ Save lr (point of interrupt)
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,5 +1,6 @@
@/***************************************************************************
@ * Copyright (c) 2024 Microsoft Corporation
@ * Copyright (c) 2026 Eclipse ThreadX contributors
@ *
@ * This program and the accompanying materials are made available under the
@ * terms of the MIT License which is available at
@@ -7,6 +8,7 @@
@ *
@ * SPDX-License-Identifier: MIT
@ **************************************************************************/
@ Some portions generated by Copilot (Opus 5).
@
@
@/**************************************************************************/
@@ -33,7 +35,6 @@
.global _tx_thread_current_ptr
.global _tx_thread_smp_protection
.global _tx_thread_preempt_disable
.global _tx_thread_smp_protect_wait_counts
.arm
.text
@@ -105,10 +106,6 @@ _tx_thread_smp_unprotect:
CMP r3, #0 @ Is the preempt disable flag set?
BNE _still_protected @ Yes, skip the protection release
LDR r2,=_tx_thread_smp_protect_wait_counts @ Build build address of wait counts
LDR r3, [r2, r1, LSL #2] @ Pickup wait list value
CMP r3, #0 @ Are any entities on this core waiting?
BNE _still_protected @ Yes, skip the protection release
LDR r2,=_tx_thread_smp_protection @ Build address of protection structure
MOV r3, #0xFFFFFFFF @ Build invalid value
@@ -1,5 +1,6 @@
;/***************************************************************************
; * Copyright (c) 2024 Microsoft Corporation
; * Copyright (c) 2026 Eclipse ThreadX contributors
; *
; * This program and the accompanying materials are made available under the
; * terms of the MIT License which is available at
@@ -7,6 +8,7 @@
; *
; * SPDX-License-Identifier: MIT
; **************************************************************************/
; Some portions generated by Copilot (Opus 5).
;
;
;/**************************************************************************/
@@ -29,8 +31,6 @@
;#include "tx_thread.h"
;#include "tx_timer.h"
;
;/* Include macros for modifying the wait list. */
#include "tx_thread_smp_protection_wait_list_macros.h"
IF :DEF:TX_ENABLE_FIQ_SUPPORT
DISABLE_INTS EQU 0xC0 ; Disable IRQ & FIQ interrupts
@@ -51,11 +51,6 @@ SVC_MODE EQU 0x93 ; SVC mode
IMPORT _tx_thread_preempt_disable
IMPORT _tx_timer_interrupt_active
IMPORT _tx_thread_smp_protection
IMPORT _tx_thread_smp_protect_wait_counts
IMPORT _tx_thread_smp_protect_wait_list
IMPORT _tx_thread_smp_protect_wait_list_lock_protect_in_force
IMPORT _tx_thread_smp_protect_wait_list_tail
IMPORT _tx_thread_smp_protect_wait_list_size
IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY
IMPORT _tx_execution_isr_exit
ENDIF
@@ -196,77 +191,6 @@ __tx_thread_no_preempt_restore
; {
;
__tx_thread_preempt_restore
;
; /* Was the thread being preempted waiting for the lock? */
; if (_tx_thread_smp_protect_wait_counts[this_core] != 0)
; {
;
LDR r1, =_tx_thread_smp_protect_wait_counts ; Load waiting count list
LDR r2, [r1, r10, LSL #2] ; Load waiting value for this core
CMP r2, #0
BEQ _nobody_waiting_for_lock ; Is the core waiting for the lock?
;
; /* Do we not have the lock? This means the ISR never got the inter-core lock. */
; if (_tx_thread_smp_protection.tx_thread_smp_protect_owned != this_core)
; {
;
LDR r1, =_tx_thread_smp_protection ; Load address of protection structure
LDR r2, [r1, #8] ; Pickup the owning core
CMP r10, r2 ; Compare our core to the owning core
BEQ _this_core_has_lock ; Do we have the lock?
;
; /* We don't have the lock. This core should be in the list. Remove it. */
; _tx_thread_smp_protect_wait_list_remove(this_core);
;
MOV r0, r10 ; Move the core ID to r0 for the macro
macro_call0 _tx_thread_smp_protect_wait_list_remove ; Call macro to remove core from the list
B _nobody_waiting_for_lock ; Leave
;
; }
; else
; {
; /* We have the lock. This means the ISR got the inter-core lock, but
; never released it because it saw that there was someone waiting.
; Note this core is not in the list. */
;
_this_core_has_lock
;
; /* We're no longer waiting. Note that this should be zero since this happens during thread preemption. */
; _tx_thread_smp_protect_wait_counts[core]--;
;
LDR r1, =_tx_thread_smp_protect_wait_counts ; Load waiting count list
LDR r2, [r1, r10, LSL #2] ; Load waiting value for this core
SUB r2, r2, #1 ; Decrement waiting value. Should be zero now
STR r2, [r1, r10, LSL #2] ; Store new waiting value
;
; /* Now release the inter-core lock. */
;
; /* Set protected core as invalid. */
; _tx_thread_smp_protection.tx_thread_smp_protect_core = 0xFFFFFFFF;
;
LDR r1, =_tx_thread_smp_protection ; Load address of protection structure
MOV r2, #0xFFFFFFFF ; Build invalid value
STR r2, [r1, #8] ; Mark the protected core as invalid
DMB ; Ensure that accesses to shared resource have completed
;
; /* Release protection. */
; _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 0;
;
MOV r2, #0 ; Build release protection value
STR r2, [r1, #0] ; Release the protection
DSB ISH ; To ensure update of the protection occurs before other CPUs awake
;
; /* Wake up waiting processors. Note interrupts are already enabled. */
;
IF :DEF:TX_ENABLE_WFE
SEV ; Send event to other CPUs
ENDIF
;
; }
; }
;
_nobody_waiting_for_lock
LDMIA sp!, {r3, r10, r12, lr} ; Recover temporarily saved registers
MOV r1, lr ; Save lr (point of interrupt)
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,5 +1,6 @@
;/***************************************************************************
; * Copyright (c) 2024 Microsoft Corporation
; * Copyright (c) 2026 Eclipse ThreadX contributors
; *
; * This program and the accompanying materials are made available under the
; * terms of the MIT License which is available at
@@ -7,6 +8,7 @@
; *
; * SPDX-License-Identifier: MIT
; **************************************************************************/
; Some portions generated by Copilot (Opus 5).
;
;
;/**************************************************************************/
@@ -33,7 +35,6 @@
IMPORT _tx_thread_current_ptr
IMPORT _tx_thread_smp_protection
IMPORT _tx_thread_preempt_disable
IMPORT _tx_thread_smp_protect_wait_counts
AREA ||.text||, CODE, READONLY
PRESERVE8
@@ -103,10 +104,6 @@ _tx_thread_smp_unprotect
CMP r3, #0 ; Is the preempt disable flag set?
BNE _still_protected ; Yes, skip the protection release
LDR r2,=_tx_thread_smp_protect_wait_counts ; Build build address of wait counts
LDR r3, [r2, r1, LSL #2] ; Pickup wait list value
CMP r3, #0 ; Are any entities on this core waiting?
BNE _still_protected ; Yes, skip the protection release
LDR r2,=_tx_thread_smp_protection ; Build address of protection structure
MOV r3, #0xFFFFFFFF ; Build invalid value
@@ -1,5 +1,6 @@
@/***************************************************************************
@ * Copyright (c) 2024 Microsoft Corporation
@ * Copyright (c) 2026 Eclipse ThreadX contributors
@ *
@ * This program and the accompanying materials are made available under the
@ * terms of the MIT License which is available at
@@ -7,6 +8,7 @@
@ *
@ * SPDX-License-Identifier: MIT
@ **************************************************************************/
@ Some portions generated by Copilot (Opus 5).
@
@
@/**************************************************************************/
@@ -29,8 +31,6 @@
@#include "tx_thread.h"
@#include "tx_timer.h"
@
@/* Include macros for modifying the wait list. */
#include "tx_thread_smp_protection_wait_list_macros.h"
#ifdef TX_ENABLE_FIQ_SUPPORT
DISABLE_INTS = 0xC0 @ Disable IRQ & FIQ interrupts
@@ -51,11 +51,6 @@ SVC_MODE = 0x93 @ SVC mode
.global _tx_thread_preempt_disable
.global _tx_timer_interrupt_active
.global _tx_thread_smp_protection
.global _tx_thread_smp_protect_wait_counts
.global _tx_thread_smp_protect_wait_list
.global _tx_thread_smp_protect_wait_list_lock_protect_in_force
.global _tx_thread_smp_protect_wait_list_tail
.global _tx_thread_smp_protect_wait_list_size
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
.global _tx_execution_isr_exit
#endif
@@ -198,77 +193,6 @@ __tx_thread_no_preempt_restore:
@ {
@
__tx_thread_preempt_restore:
@
@ /* Was the thread being preempted waiting for the lock? */
@ if (_tx_thread_smp_protect_wait_counts[this_core] != 0)
@ {
@
LDR r1, =_tx_thread_smp_protect_wait_counts @ Load waiting count list
LDR r2, [r1, r10, LSL #2] @ Load waiting value for this core
CMP r2, #0
BEQ _nobody_waiting_for_lock @ Is the core waiting for the lock?
@
@ /* Do we not have the lock? This means the ISR never got the inter-core lock. */
@ if (_tx_thread_smp_protection.tx_thread_smp_protect_owned != this_core)
@ {
@
LDR r1, =_tx_thread_smp_protection @ Load address of protection structure
LDR r2, [r1, #8] @ Pickup the owning core
CMP r10, r2 @ Compare our core to the owning core
BEQ _this_core_has_lock @ Do we have the lock?
@
@ /* We don't have the lock. This core should be in the list. Remove it. */
@ _tx_thread_smp_protect_wait_list_remove(this_core);
@
MOV r0, r10 @ Move the core ID to r0 for the macro
_tx_thread_smp_protect_wait_list_remove @ Call macro to remove core from the list
B _nobody_waiting_for_lock @ Leave
@
@ }
@ else
@ {
@ /* We have the lock. This means the ISR got the inter-core lock, but
@ never released it because it saw that there was someone waiting.
@ Note this core is not in the list. */
@
_this_core_has_lock:
@
@ /* We're no longer waiting. Note that this should be zero since this happens during thread preemption. */
@ _tx_thread_smp_protect_wait_counts[core]--;
@
LDR r1, =_tx_thread_smp_protect_wait_counts @ Load waiting count list
LDR r2, [r1, r10, LSL #2] @ Load waiting value for this core
SUB r2, r2, #1 @ Decrement waiting value. Should be zero now
STR r2, [r1, r10, LSL #2] @ Store new waiting value
@
@ /* Now release the inter-core lock. */
@
@ /* Set protected core as invalid. */
@ _tx_thread_smp_protection.tx_thread_smp_protect_core = 0xFFFFFFFF;
@
LDR r1, =_tx_thread_smp_protection @ Load address of protection structure
MOV r2, #0xFFFFFFFF @ Build invalid value
STR r2, [r1, #8] @ Mark the protected core as invalid
DMB @ Ensure that accesses to shared resource have completed
@
@ /* Release protection. */
@ _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 0;
@
MOV r2, #0 @ Build release protection value
STR r2, [r1, #0] @ Release the protection
DSB ISH @ To ensure update of the protection occurs before other CPUs awake
@
@ /* Wake up waiting processors. Note interrupts are already enabled. */
@
#ifdef TX_ENABLE_WFE
SEV @ Send event to other CPUs
#endif
@
@ }
@ }
@
_nobody_waiting_for_lock:
LDMIA sp!, {r3, r10, r12, lr} @ Recover temporarily saved registers
MOV r1, lr @ Save lr (point of interrupt)
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,5 +1,6 @@
@/***************************************************************************
@ * Copyright (c) 2024 Microsoft Corporation
@ * Copyright (c) 2026 Eclipse ThreadX contributors
@ *
@ * This program and the accompanying materials are made available under the
@ * terms of the MIT License which is available at
@@ -7,6 +8,7 @@
@ *
@ * SPDX-License-Identifier: MIT
@ **************************************************************************/
@ Some portions generated by Copilot (Opus 5).
@
@
@/**************************************************************************/
@@ -33,7 +35,6 @@
.global _tx_thread_current_ptr
.global _tx_thread_smp_protection
.global _tx_thread_preempt_disable
.global _tx_thread_smp_protect_wait_counts
.arm
.text
@@ -105,10 +106,6 @@ _tx_thread_smp_unprotect:
CMP r3, #0 @ Is the preempt disable flag set?
BNE _still_protected @ Yes, skip the protection release
LDR r2,=_tx_thread_smp_protect_wait_counts @ Build build address of wait counts
LDR r3, [r2, r1, LSL #2] @ Pickup wait list value
CMP r3, #0 @ Are any entities on this core waiting?
BNE _still_protected @ Yes, skip the protection release
LDR r2,=_tx_thread_smp_protection @ Build address of protection structure
MOV r3, #0xFFFFFFFF @ Build invalid value