summaryrefslogtreecommitdiff
path: root/test/tx/regression/threadx_thread_misaligned_stack_test.c
diff options
context:
space:
mode:
authorFrédéric Desbiens <[email protected]>2026-10-02 10:42:44 -0400
committerGitHub <[email protected]>2026-10-02 10:42:44 -0400
commit93387b0a60382a29579bbad5045c68328e3751df (patch)
tree42be790d602cb76f55090e5a7c418df7ea2b3428 /test/tx/regression/threadx_thread_misaligned_stack_test.c
parent44d7c95c582d415c4ad84527180b29c93c3bf664 (diff)
parent28281cd5647d4671236ca08d19bd18ed15b2265a (diff)
Merge pull request #783 from eclipse-threadx/devv6.5.2.202603_rel
Merged changes ahead of the v6.5.2.202603 release
Diffstat (limited to 'test/tx/regression/threadx_thread_misaligned_stack_test.c')
-rw-r--r--test/tx/regression/threadx_thread_misaligned_stack_test.c150
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++;
+}