Fixed RISC-V regression portability failures (#773)
cortex_m / Cortex M0 build (push) Canceled after 0s
cortex_m / Cortex M3 build (push) Canceled after 0s
cortex_m / Cortex M4 build (push) Canceled after 0s
cortex_m / Cortex M7 build (push) Canceled after 0s
regression_test / tx (push) Canceled after 0s
regression_test / smp (push) Canceled after 0s
regression_test / freertos (push) Canceled after 0s
regression_test / riscv (push) Canceled after 0s
regression_test / deploy (push) Canceled after 0s
regression_template / run_tests (push) Canceled after 0s
regression_template / deploy_code_coverage (push) Canceled after 0s

RISC-V regression builds ran only at -O0, leaving a timer callback counter that
spins forever at -O2. The trace regression was excluded because it referenced
a port-specific interrupt-save variable, and its adjacent pools could start
misaligned on RV64.

Made the timer counter volatile, gave the trace test aligned pool storage and a
portable saved-interrupt value, and enabled it on RISC-V. Added an -O2 QEMU
configuration to keep the optimized failure covered.

CMake/Ninja/QEMU: RV64 default, optimized and trace suites passed 97/97 each;
RV32 passed 96/96 each. Two ISR event tests passed 30 repeats each at -O2.
The Linux/GCC 14 trace test passed. The reported timing resonance did not recur.

Assisted-by: Codex (gpt-6-sol) <noreply@openai.com>
This commit is contained in:
Frédéric Desbiens
2026-09-23 16:52:44 -04:00
committed by GitHub
parent 70a5300977
commit b37cd4a81a
4 changed files with 40 additions and 24 deletions
+9 -2
View File
@@ -5,7 +5,7 @@ cmake_policy(SET CMP0057 NEW)
project(threadx_riscv_test LANGUAGES C ASM)
# Build configurations (same defines as Linux tests, minus coverage instrumentation)
set(BUILD_CONFIGURATIONS default_build disable_notify_callbacks_build
set(BUILD_CONFIGURATIONS default_build optimized_build disable_notify_callbacks_build
stack_checking_build stack_checking_rand_fill_build trace_build)
set(CMAKE_CONFIGURATION_TYPES
${BUILD_CONFIGURATIONS}
@@ -26,14 +26,21 @@ message(STATUS "THREADX_ARCH: ${THREADX_ARCH}")
# Per-configuration compile definitions
set(default_build -DTX_QUEUE_MESSAGE_MAX_SIZE=32)
set(optimized_build -DTX_QUEUE_MESSAGE_MAX_SIZE=32)
set(disable_notify_callbacks_build -DTX_QUEUE_MESSAGE_MAX_SIZE=32 -DTX_DISABLE_NOTIFY_CALLBACKS)
set(stack_checking_build -DTX_QUEUE_MESSAGE_MAX_SIZE=32 -DTX_ENABLE_STACK_CHECKING)
set(stack_checking_rand_fill_build -DTX_QUEUE_MESSAGE_MAX_SIZE=32 -DTX_ENABLE_STACK_CHECKING -DTX_ENABLE_RANDOM_NUMBER_STACK_FILLING)
set(trace_build -DTX_QUEUE_MESSAGE_MAX_SIZE=32 -DTX_ENABLE_EVENT_TRACE)
if(CMAKE_BUILD_TYPE STREQUAL "optimized_build")
set(REGRESSION_OPTIMIZATION -O2)
else()
set(REGRESSION_OPTIMIZATION -O0)
endif()
add_compile_options(
-std=c99
-O0
${REGRESSION_OPTIMIZATION}
-g3
-fdiagnostics-color
-Werror
@@ -110,9 +110,7 @@ set(regression_test_cases
${SOURCE_DIR}/threadx_timer_multiple_accuracy_test.c
${SOURCE_DIR}/threadx_timer_multiple_test.c
${SOURCE_DIR}/threadx_timer_simple_test.c
# threadx_trace_basic_test.c excluded: references tx_saved_posture
# (the Linux port's interrupt save variable) which is named
# interrupt_save on RISC-V.
${SOURCE_DIR}/threadx_trace_basic_test.c
)
# Architecture specific tests living next to this file. The RV32 stack
@@ -9,6 +9,8 @@
/* SPDX-License-Identifier: MIT */
/***************************************************************************/
/* Portions of this file were generated with AI assistance. */
/* This test is designed to test multi-level preemption threshold. The protection placed
by a thread must be preserved after higher-priority thread preemption that is above the threshold. */
@@ -74,7 +76,7 @@ static TX_TIMER timer_0;
/* Define counters. */
static unsigned long timer_0_counter = 0;
static volatile unsigned long timer_0_counter = 0;
static unsigned long thread_1_0_counter = 0;
static unsigned long thread_2_1_counter = 0;
static unsigned long thread_3_2_counter = 0;
+27 -18
View File
@@ -9,6 +9,8 @@
/* SPDX-License-Identifier: MIT */
/***************************************************************************/
/* Portions of this file were generated with AI assistance. */
/* This test is designed to test trace functionality in ThreadX. */
@@ -66,6 +68,16 @@ static unsigned long error = 0;
static unsigned long full_buffer = 0;
static void *save_pointer;
#define TRACE_BLOCK_POOL_SIZE ((ULONG) (((100U + sizeof(ALIGN_TYPE) - 1U) / sizeof(ALIGN_TYPE)) * sizeof(ALIGN_TYPE)))
#define TRACE_BYTE_POOL_SIZE ((ULONG) (((1000U + sizeof(ALIGN_TYPE) - 1U) / sizeof(ALIGN_TYPE)) * sizeof(ALIGN_TYPE)))
/* Keep pool storage aligned for ports with pointer-wide metadata. */
static struct
{
ALIGN_TYPE alignment;
CHAR bytes[TRACE_BLOCK_POOL_SIZE + TRACE_BYTE_POOL_SIZE + 400U];
} object_memory;
#if defined(TX_WIN32_MEMORY_SIZE) || defined(TX_LINUX_MEMORY_SIZE)
static FILE *trace_dump_file;
@@ -185,25 +197,21 @@ INT status;
CHAR *pointer;
/* Setup a pointer. */
pointer = (CHAR *) first_unused_memory;
/* Adjust it forward just to make sure there is some space for the test below. */
pointer = pointer + 200;
/* Setup aligned object storage. */
pointer = object_memory.bytes;
/* Create a bunch of objects before being enabled. */
/* Create a timer for the test. */
save_pointer = (void *) pointer;
tx_timer_create(&timer_0, "timer 0", timer_entry, 0, 2, 2, TX_AUTO_ACTIVATE);
tx_block_pool_create(&block_pool_0, "block pool 0", 20, pointer, 100);
pointer = pointer + 100;
tx_byte_pool_create(&byte_pool_0, "byte pool 0", pointer, 1000);
pointer = pointer + 1000;
tx_block_pool_create(&block_pool_0, "block pool 0", 20, pointer, TRACE_BLOCK_POOL_SIZE);
pointer = pointer + TRACE_BLOCK_POOL_SIZE;
tx_byte_pool_create(&byte_pool_0, "byte pool 0", pointer, TRACE_BYTE_POOL_SIZE);
pointer = pointer + TRACE_BYTE_POOL_SIZE;
tx_event_flags_create(&group_0, "event flags group 0");
tx_mutex_create(&mutex_0, "mutex 0", TX_NO_INHERIT);
tx_queue_create(&queue_0, "queue 0", 16, pointer, 400);
pointer = pointer + 400;
tx_semaphore_create(&semaphore_0, "semaphore 0", 1);
/* Enable event tracing. */
@@ -230,6 +238,9 @@ CHAR *pointer;
}
#endif
pointer = (CHAR *) first_unused_memory;
pointer = pointer + 200;
/* Put system definition stuff in here, e.g. thread creates and other assorted
create information. */
@@ -281,12 +292,11 @@ static void thread_0_entry(ULONG thread_input)
UINT status;
UINT old_interrupt;
CHAR *pointer;
TX_INTERRUPT_SAVE_AREA
ULONG object;
/* Coverage for build without TraceX enabled. */
tx_saved_posture = _tx_trace_interrupt_control(TX_INT_DISABLE);
_tx_trace_interrupt_control(tx_saved_posture);
old_interrupt = _tx_trace_interrupt_control(TX_INT_DISABLE);
_tx_trace_interrupt_control(old_interrupt);
#ifndef TX_ENABLE_EVENT_TRACE
_tx_trace_object_register(0, TX_NULL, TX_NULL, 0, 0);
_tx_trace_object_register(1, TX_NULL, TX_NULL, 0, 0);
@@ -354,14 +364,13 @@ ULONG object;
/* Now, create them all again. */
pointer = (CHAR *) save_pointer;
tx_block_pool_create(&block_pool_0, "block pool 0", 20, pointer, 100);
pointer = pointer + 100;
tx_byte_pool_create(&byte_pool_0, "byte pool 0", pointer, 1000);
pointer = pointer + 1000;
tx_block_pool_create(&block_pool_0, "block pool 0", 20, pointer, TRACE_BLOCK_POOL_SIZE);
pointer = pointer + TRACE_BLOCK_POOL_SIZE;
tx_byte_pool_create(&byte_pool_0, "byte pool 0", pointer, TRACE_BYTE_POOL_SIZE);
pointer = pointer + TRACE_BYTE_POOL_SIZE;
tx_event_flags_create(&group_0, "event flags group 0");
tx_mutex_create(&mutex_0, "mutex 0", TX_NO_INHERIT);
tx_queue_create(&queue_0, "queue 0", 16, pointer, 400);
pointer = pointer + 400;
tx_semaphore_create(&semaphore_0, "semaphore 0", 1);
/* Attempt to enable event tracing again. */