Skip to content

Commit c05ba69

Browse files
committed
Fix race condition and message loss in Cortex-M GNU ports (#516)
- Added compiler memory barriers to BASEPRI management functions in tx_port.h. - Added architectural barriers (DSB/ISB) to scheduler return paths in tx_port.h and tx_thread_system_return.S to prevent fall-through before context switch. - These changes address spurious thread resumption and lost messages, especially when TX_NOT_INTERRUPTABLE is enabled. Assisted-by: Gemini (Gemini 2.0 Flash)
1 parent 8c57362 commit c05ba69

File tree

16 files changed

+77
-17
lines changed

16 files changed

+77
-17
lines changed

ports/cortex_m0/gnu/inc/tx_port.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
* SPDX-License-Identifier: MIT
1010
**************************************************************************/
1111

12+
// Some portions generated by Gemini (Gemini 2.0 Flash).
13+
1214

1315
/**************************************************************************/
1416
/**************************************************************************/
@@ -322,6 +324,7 @@ unsigned int interrupt_save;
322324

323325
/* Set PendSV to invoke ThreadX scheduler. */
324326
*((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
327+
__asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory");
325328
if (__get_ipsr_value() == 0)
326329
{
327330
interrupt_save = __get_primask_value();

ports/cortex_m0/gnu/src/tx_thread_system_return.S

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@
55
@ * terms of the MIT License which is available at
66
@ * https://opensource.org/licenses/MIT.
77
@ *
8-
@ * SPDX-License-Identifier: MIT
9-
@ **************************************************************************/
10-
@
11-
@
12-
@/**************************************************************************/
8+
* SPDX-License-Identifier: MIT
9+
**************************************************************************/
10+
11+
// Some portions generated by Gemini (Gemini 2.0 Flash).
12+
13+
14+
/**************************************************************************/
15+
1316
@/**************************************************************************/
1417
@/** */
1518
@/** ThreadX Component */
@@ -72,6 +75,8 @@ _tx_thread_system_return:
7275
LDR r0, =0x10000000 @ Load PENDSVSET bit
7376
LDR r1, =0xE000ED04 @ Load NVIC base
7477
STR r0, [r1] @ Set PENDSVBIT in ICSR
78+
DSB #0xF @ Ensure memory access is complete
79+
ISB #0xF @ Flush pipeline
7580
MRS r0, IPSR @ Pickup IPSR
7681
CMP r0, #0 @ Is it a thread returning?
7782
BNE _isr_context @ If ISR, skip interrupt enable

ports/cortex_m23/gnu/inc/tx_port.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
* SPDX-License-Identifier: MIT
1010
**************************************************************************/
1111

12+
// Some portions generated by Gemini (Gemini 2.0 Flash).
13+
1214

1315
/**************************************************************************/
1416
/**************************************************************************/
@@ -389,6 +391,7 @@ unsigned int interrupt_save;
389391

390392
/* Set PendSV to invoke ThreadX scheduler. */
391393
*((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
394+
__asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory");
392395
if (_get_ipsr() == 0)
393396
{
394397
interrupt_save = __get_primask_value();

ports/cortex_m23/gnu/src/tx_thread_system_return.S

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
* SPDX-License-Identifier: MIT
1010
**************************************************************************/
1111

12+
// Some portions generated by Gemini (Gemini 2.0 Flash).
13+
1214

1315
/**************************************************************************/
1416
/**************************************************************************/
@@ -74,6 +76,8 @@ _tx_thread_system_return:
7476
LDR r0, =0x10000000 // Load PENDSVSET bit
7577
LDR r1, =0xE000ED04 // Load ICSR address
7678
STR r0, [r1] // Set PENDSVBIT in ICSR
79+
DSB #0xF // Ensure memory access is complete
80+
ISB #0xF // Flush pipeline
7781
MRS r0, IPSR // Pickup IPSR
7882
CMP r0, #0 // Is it a thread returning?
7983
BNE _isr_context // If ISR, skip interrupt enable

ports/cortex_m3/gnu/inc/tx_port.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
* SPDX-License-Identifier: MIT
1010
**************************************************************************/
1111

12+
// Some portions generated by Gemini (Gemini 2.0 Flash).
13+
1214

1315
/**************************************************************************/
1416
/**************************************************************************/
@@ -539,7 +541,7 @@ unsigned int posture;
539541
#ifdef TX_PORT_USE_BASEPRI
540542
__attribute__( ( always_inline ) ) static inline void __set_basepri_value(unsigned int basepri_value)
541543
{
542-
__asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value));
544+
__asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value) : "memory");
543545
}
544546
#else
545547
__attribute__( ( always_inline ) ) static inline void __enable_interrupts(void)
@@ -552,7 +554,6 @@ __attribute__( ( always_inline ) ) static inline void __restore_interrupt(unsign
552554
{
553555
#ifdef TX_PORT_USE_BASEPRI
554556
__set_basepri_value(int_posture);
555-
//__asm__ volatile ("MSR BASEPRI,%0": : "r" (int_posture): "memory");
556557
#else
557558
__asm__ volatile ("MSR PRIMASK,%0": : "r" (int_posture): "memory");
558559
#endif
@@ -578,6 +579,7 @@ unsigned int interrupt_save;
578579

579580
/* Set PendSV to invoke ThreadX scheduler. */
580581
*((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
582+
__asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory");
581583
if (__get_ipsr_value() == 0)
582584
{
583585
interrupt_save = __get_interrupt_posture();

ports/cortex_m3/gnu/src/tx_thread_system_return.S

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
* SPDX-License-Identifier: MIT
1010
**************************************************************************/
1111

12+
// Some portions generated by Gemini (Gemini 2.0 Flash).
13+
1214

1315
/**************************************************************************/
1416
/**************************************************************************/
@@ -73,6 +75,8 @@ _tx_thread_system_return:
7375
MOV r0, #0x10000000 // Load PENDSVSET bit
7476
MOV r1, #0xE000E000 // Load NVIC base
7577
STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
78+
DSB #0xF // Ensure memory access is complete
79+
ISB #0xF // Flush pipeline
7680
MRS r0, IPSR // Pickup IPSR
7781
CMP r0, #0 // Is it a thread returning?
7882
BNE _isr_context // If ISR, skip interrupt enable

ports/cortex_m33/gnu/inc/tx_port.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
* SPDX-License-Identifier: MIT
1010
**************************************************************************/
1111

12+
// Some portions generated by Gemini (Gemini 2.0 Flash).
13+
1214

1315
/**************************************************************************/
1416
/**************************************************************************/
@@ -541,7 +543,7 @@ UINT posture;
541543
#ifdef TX_PORT_USE_BASEPRI
542544
__attribute__( ( always_inline ) ) static inline void __set_basepri_value(UINT basepri_value)
543545
{
544-
__asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value));
546+
__asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value) : "memory");
545547
}
546548
#else
547549
__attribute__( ( always_inline ) ) static inline void __enable_interrupts(void)
@@ -579,6 +581,7 @@ UINT interrupt_save;
579581

580582
/* Set PendSV to invoke ThreadX scheduler. */
581583
*((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
584+
__asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory");
582585
if (_tx_ipsr_get() == 0)
583586
{
584587
interrupt_save = __get_interrupt_posture();

ports/cortex_m33/gnu/src/tx_thread_system_return.S

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
* SPDX-License-Identifier: MIT
1010
**************************************************************************/
1111

12+
// Some portions generated by Gemini (Gemini 2.0 Flash).
13+
1214

1315
/**************************************************************************/
1416
/**************************************************************************/
@@ -74,6 +76,8 @@ _tx_thread_system_return:
7476
MOV r0, #0x10000000 // Load PENDSVSET bit
7577
MOV r1, #0xE000E000 // Load NVIC base
7678
STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
79+
DSB #0xF // Ensure memory access is complete
80+
ISB #0xF // Flush pipeline
7781
MRS r0, IPSR // Pickup IPSR
7882
CMP r0, #0 // Is it a thread returning?
7983
BNE _isr_context // If ISR, skip interrupt enable

ports/cortex_m4/gnu/inc/tx_port.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
* SPDX-License-Identifier: MIT
1010
**************************************************************************/
1111

12+
// Some portions generated by Gemini (Gemini 2.0 Flash).
13+
1214

1315
/**************************************************************************/
1416
/**************************************************************************/
@@ -539,9 +541,10 @@ unsigned int posture;
539541
#ifdef TX_PORT_USE_BASEPRI
540542
__attribute__( ( always_inline ) ) static inline void __set_basepri_value(unsigned int basepri_value)
541543
{
542-
__asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value));
544+
__asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value) : "memory");
543545
}
544-
#else
546+
#endif
547+
545548
__attribute__( ( always_inline ) ) static inline void __enable_interrupts(void)
546549
{
547550
__asm__ volatile ("CPSIE i": : : "memory");
@@ -552,7 +555,7 @@ __attribute__( ( always_inline ) ) static inline void __restore_interrupt(unsign
552555
{
553556
#ifdef TX_PORT_USE_BASEPRI
554557
__set_basepri_value(int_posture);
555-
//__asm__ volatile ("MSR BASEPRI,%0": : "r" (int_posture): "memory");
558+
__asm__ volatile ("" : : : "memory");
556559
#else
557560
__asm__ volatile ("MSR PRIMASK,%0": : "r" (int_posture): "memory");
558561
#endif
@@ -578,6 +581,7 @@ unsigned int interrupt_save;
578581

579582
/* Set PendSV to invoke ThreadX scheduler. */
580583
*((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000);
584+
__asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory");
581585
if (__get_ipsr_value() == 0)
582586
{
583587
interrupt_save = __get_interrupt_posture();

ports/cortex_m4/gnu/src/tx_thread_system_return.S

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
* SPDX-License-Identifier: MIT
1010
**************************************************************************/
1111

12+
// Some portions generated by Gemini (Gemini 2.0 Flash).
13+
1214

1315
/**************************************************************************/
1416
/**************************************************************************/
@@ -73,6 +75,8 @@ _tx_thread_system_return:
7375
MOV r0, #0x10000000 // Load PENDSVSET bit
7476
MOV r1, #0xE000E000 // Load NVIC base
7577
STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR
78+
DSB #0xF // Ensure memory access is complete
79+
ISB #0xF // Flush pipeline
7680
MRS r0, IPSR // Pickup IPSR
7781
CMP r0, #0 // Is it a thread returning?
7882
BNE _isr_context // If ISR, skip interrupt enable

0 commit comments

Comments
 (0)