summaryrefslogtreecommitdiff
path: root/test/smp/regression/threadx_thread_stack_fill_value_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/smp/regression/threadx_thread_stack_fill_value_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/smp/regression/threadx_thread_stack_fill_value_test.c')
-rw-r--r--test/smp/regression/threadx_thread_stack_fill_value_test.c190
1 files changed, 190 insertions, 0 deletions
diff --git a/test/smp/regression/threadx_thread_stack_fill_value_test.c b/test/smp/regression/threadx_thread_stack_fill_value_test.c
new file mode 100644
index 00000000..fa6eda22
--- /dev/null
+++ b/test/smp/regression/threadx_thread_stack_fill_value_test.c
@@ -0,0 +1,190 @@
+/***************************************************************************/
+/* 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. */
+/* */
+/* SPDX-License-Identifier: MIT */
+/***************************************************************************/
+
+// Portions of this file were generated with AI assistance.
+
+/* This test checks that the stack fill value recorded in a thread control block is the
+ value that was actually written into that thread's stack. The two used to disagree
+ when TX_ENABLE_RANDOM_NUMBER_STACK_FILLING was enabled, because the control block was
+ cleared after the random value had been chosen and the stack had been filled with it,
+ which left the stack checking and stack analyze routines looking for a pattern that is
+ not the one present in the stack. */
+
+#include <stdio.h>
+#include "tx_api.h"
+
+
+/* Number of probe threads created. A random fill value can legitimately come out as zero,
+ which hides the defect for that one thread, so several threads are created and at least
+ one of them is required to have produced a non-zero pattern. */
+
+#define TEST_PROBE_THREADS 16
+
+
+static unsigned long thread_0_counter = 0;
+static TX_THREAD thread_0;
+
+static TX_THREAD probe_thread;
+static ULONG probe_stack[TX_MINIMUM_STACK / sizeof(ULONG)];
+
+
+/* Define task prototypes. */
+
+static void thread_0_entry(ULONG task_input);
+
+
+/* Prototype for test control return. */
+
+void test_control_return(UINT status);
+
+
+/* Define what the initial system looks like. */
+
+#ifdef CTEST
+void test_application_define(void *first_unused_memory)
+#else
+void threadx_thread_stack_fill_value_application_define(void *first_unused_memory)
+#endif
+{
+
+UINT status;
+CHAR *pointer;
+
+ pointer = (CHAR *) first_unused_memory;
+
+ /* Put system definition stuff in here, e.g. thread creates and other assorted
+ create information. */
+
+ 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);
+
+ /* Check for status. */
+ if (status != TX_SUCCESS)
+ {
+
+ printf("Running Thread Stack Fill Value Test................................ ERROR #1\n");
+ test_control_return(1);
+ }
+}
+
+
+/* Define the test threads. */
+
+static void thread_0_entry(ULONG thread_input)
+{
+
+UINT status;
+UINT i;
+ULONG stack_pattern;
+UINT non_zero_seen = TX_FALSE;
+
+
+ /* Increment thread 0 counter. */
+ thread_0_counter++;
+
+ /* Inform user of success getting to this test. */
+ printf("Running Thread Stack Fill Value Test................................ ");
+
+ for (i = 0; i < TEST_PROBE_THREADS; i++)
+ {
+
+ /* Create a thread that is never started, so that its stack still holds nothing but
+ the fill pattern and the initial stack frame built at the top of the stack. */
+ status = tx_thread_create(&probe_thread, "probe thread", thread_0_entry, 0,
+ probe_stack, sizeof(probe_stack),
+ 17, 17, TX_NO_TIME_SLICE, TX_DONT_START);
+
+ /* Check for status. */
+ if (status != TX_SUCCESS)
+ {
+
+ printf("ERROR #2\n");
+ test_control_return(1);
+ }
+
+ /* Pick up the pattern the create service wrote into the unused part of the stack. */
+ stack_pattern = *(((ULONG *) probe_thread.tx_thread_stack_start) + 4);
+
+#ifndef TX_DISABLE_STACK_FILLING
+#if defined(TX_ENABLE_RANDOM_NUMBER_STACK_FILLING) && defined(TX_ENABLE_STACK_CHECKING)
+
+ /* The control block must hold the value that was written into the stack. */
+ if (probe_thread.tx_thread_stack_fill_value != stack_pattern)
+ {
+
+ printf("ERROR #3\n");
+ test_control_return(1);
+ }
+
+ /* The random value is duplicated into all four bytes of the fill value. */
+ if ((stack_pattern & 0xFFUL) !=
+ ((stack_pattern >> 24) & 0xFFUL))
+ {
+
+ printf("ERROR #4\n");
+ test_control_return(1);
+ }
+
+ if (stack_pattern != ((ULONG) 0))
+ {
+
+ non_zero_seen = TX_TRUE;
+ }
+#else
+
+ /* Without random filling, the pattern is the fixed one. */
+ if (stack_pattern != ((ULONG) 0xEFEFEFEFUL))
+ {
+
+ printf("ERROR #5\n");
+ test_control_return(1);
+ }
+
+ non_zero_seen = TX_TRUE;
+#endif
+#else
+
+ /* Stack filling is disabled, so there is nothing to compare. */
+ non_zero_seen = TX_TRUE;
+#endif
+
+ /* Terminate and delete the probe thread so that the next pass starts from a clean
+ slate. A thread created with TX_DONT_START is suspended rather than completed,
+ so it must be terminated before it can be deleted. */
+ status = tx_thread_terminate(&probe_thread);
+
+ if (status == TX_SUCCESS)
+ {
+
+ status = tx_thread_delete(&probe_thread);
+ }
+
+ /* Check for status. */
+ if (status != TX_SUCCESS)
+ {
+
+ printf("ERROR #6\n");
+ test_control_return(1);
+ }
+ }
+
+ /* A run in which every fill value came out as zero would prove nothing. */
+ if (non_zero_seen != TX_TRUE)
+ {
+
+ printf("ERROR #7\n");
+ test_control_return(1);
+ }
+
+ /* Success! */
+ printf("SUCCESS!\n");
+ test_control_return(0);
+}