diff options
Diffstat (limited to 'test/tx/regression/threadx_thread_misaligned_stack_test.c')
| -rw-r--r-- | test/tx/regression/threadx_thread_misaligned_stack_test.c | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/test/tx/regression/threadx_thread_misaligned_stack_test.c b/test/tx/regression/threadx_thread_misaligned_stack_test.c new file mode 100644 index 00000000..63d64775 --- /dev/null +++ b/test/tx/regression/threadx_thread_misaligned_stack_test.c @@ -0,0 +1,150 @@ +/*************************************************************************** + * 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 + * https://opensource.org/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* This test creates a thread whose stack does not begin on a ULONG boundary. + + tx_thread_create rounds the starting address up to the next ULONG and then + takes a ULONG off the size, so that the rounding cannot push the end of the + stack past the memory the caller supplied: + + if (new_stack_start != updated_stack_start) + { + stack_size = stack_size - (sizeof(ULONG)); + } + + Every other test in the suite hands tx_thread_create an aligned stack, so + that subtraction was never executed -- the only uncovered line in + tx_thread_create.c across all five build configurations. A misaligned stack + is legitimate: the API takes a VOID * and the alignment fix-up exists + precisely to accept one. + + The thread is then run to completion rather than merely created, because the + point of the adjustment is that the resulting stack is still usable and still + inside the caller's buffer. */ + +#include <stdio.h> +#include "tx_api.h" + + +void test_control_return(UINT status); + + +static TX_THREAD thread_0; +static TX_THREAD thread_1; + +/* Thread 1's stack is carved out of this by hand so that its start can be put + deliberately off a ULONG boundary. The extra ULONG is what the misaligned + start is offset into, so that the stack still ends inside the array after + tx_thread_create has rounded the start up. */ + +static UCHAR misaligned_area[TEST_STACK_SIZE_PRINTF + sizeof(ULONG)]; + +static ULONG thread_1_counter = 0; + + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_misaligned_stack_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; +CHAR *misaligned_stack; + + + /* Setup a pointer. */ + pointer = (CHAR *) first_unused_memory; + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + if (status != TX_SUCCESS) + { + + printf("Running Thread Misaligned Stack Test................................ ERROR #1\n"); + test_control_return(1); + } + + /* Push the start one byte past a ULONG boundary. The array itself is + aligned, so adding one is enough to guarantee the fix-up runs whatever + the alignment of the array turned out to be. */ + misaligned_stack = ((CHAR *) misaligned_area) + 1; + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 0, + misaligned_stack, TEST_STACK_SIZE_PRINTF, + 15, 15, TX_NO_TIME_SLICE, TX_AUTO_START); + + if (status != TX_SUCCESS) + { + + printf("Running Thread Misaligned Stack Test................................ ERROR #2\n"); + test_control_return(1); + } +} + + +static void thread_0_entry(ULONG thread_input) +{ + + /* Thread 1 is the higher priority of the two, so this thread first gets the + processor while thread 1 is sleeping. Sleep past that, so the check below + is made against a thread that has actually finished. */ + tx_thread_sleep(5); + + /* Both increments must have happened: one before thread 1 slept and one + after it woke, which is the half that needed the stack to survive a + context switch. */ + if (thread_1_counter != ((ULONG) 2)) + { + + printf("Running Thread Misaligned Stack Test................................ ERROR #3\n"); + test_control_return(1); + } + + /* The thread that ran on the misaligned stack must have run to completion, + which is what says the adjusted stack was usable. */ + if (thread_1.tx_thread_state != TX_COMPLETED) + { + + printf("Running Thread Misaligned Stack Test................................ ERROR #4\n"); + test_control_return(1); + } + + printf("Running Thread Misaligned Stack Test................................ SUCCESS!\n"); + test_control_return(0); +} + + +static void thread_1_entry(ULONG thread_input) +{ + + /* Use the stack either side of a context switch rather than returning + straight away. */ + thread_1_counter++; + + tx_thread_sleep(1); + + thread_1_counter++; +} |
