1 /* This test is for the thread stack checking services. */
2
3 #include <stdio.h>
4 #include "tx_api.h"
5
6
7 /* Prototype for direct call. */
8
9 VOID _tx_thread_stack_analyze(TX_THREAD *thread_ptr);
10
11
12
13 static unsigned long thread_0_counter = 0;
14 static TX_THREAD thread_0;
15
16 static unsigned long thread_1_counter = 0;
17 static TX_THREAD thread_1;
18
19 static unsigned long thread_2_counter = 0;
20 static TX_THREAD thread_2;
21 static CHAR *thread_2_stack_start;
22 static UINT stack_error = 0;
23
24
25 /* Define task prototypes. */
26
27 static void thread_0_entry(ULONG task_input);
28 static void thread_1_entry(ULONG task_input);
29 static void thread_2_entry(ULONG task_input);
30
31
32 /* Prototype for test control return. */
33
34 void test_control_return(UINT status);
35
36
37 /* Define the stack checking error handler. */
38
stack_error_handler(TX_THREAD * thread_ptr)39 void stack_error_handler(TX_THREAD *thread_ptr)
40 {
41
42 /* Check for the right thread. */
43 if (thread_ptr == &thread_2)
44 stack_error = 1;
45 }
46
47
48 /* Define what the initial system looks like. */
49
50 #ifdef CTEST
test_application_define(void * first_unused_memory)51 void test_application_define(void *first_unused_memory)
52 #else
53 void threadx_thread_stack_checking_application_define(void *first_unused_memory)
54 #endif
55 {
56
57 INT status;
58 CHAR *pointer;
59
60 pointer = (CHAR *) first_unused_memory;
61
62 /* Put system definition stuff in here, e.g. thread creates and other assorted
63 create information. */
64
65 status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,
66 pointer, TEST_STACK_SIZE_PRINTF,
67 15, 15, TX_NO_TIME_SLICE, TX_AUTO_START);
68 pointer = pointer + TEST_STACK_SIZE_PRINTF;
69
70 /* Check for status. */
71 if (status != TX_SUCCESS)
72 {
73
74 printf("Running Thread Stack Checking Test.................................. ERROR #1\n");
75 test_control_return(1);
76 }
77
78 status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1,
79 pointer, TEST_STACK_SIZE_PRINTF,
80 16, 16, TX_NO_TIME_SLICE, TX_DONT_START);
81 pointer = pointer + TEST_STACK_SIZE_PRINTF;
82
83 /* Check for status. */
84 if (status != TX_SUCCESS)
85 {
86
87 printf("Running Thread Stack Checking Test.................................. ERROR #2\n");
88 test_control_return(1);
89 }
90
91 status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2,
92 pointer, TEST_STACK_SIZE_PRINTF,
93 17, 17, TX_NO_TIME_SLICE, TX_DONT_START);
94 thread_2_stack_start = pointer;
95 pointer = pointer + TEST_STACK_SIZE_PRINTF;
96
97 /* Check for status. */
98 if (status != TX_SUCCESS)
99 {
100
101 printf("Running Thread Stack Checking Test.................................. ERROR #3\n");
102 test_control_return(1);
103 }
104
105 /* Register the stack checking handler. */
106 status = tx_thread_stack_error_notify(stack_error_handler);
107
108 #ifdef TX_ENABLE_STACK_CHECKING
109 /* Check for status. */
110 if (status != TX_SUCCESS)
111 #else
112 if (status != TX_FEATURE_NOT_ENABLED)
113 #endif
114
115 {
116
117 printf("Running Thread Stack Checking Test.................................. ERROR #4\n");
118 test_control_return(1);
119 }
120 }
121
122
123
124 /* Define the test threads. */
125
thread_0_entry(ULONG thread_input)126 static void thread_0_entry(ULONG thread_input)
127 {
128
129 UINT status;
130
131
132 /* Increment thread 0 counter. */
133 thread_0_counter++;
134
135 /* Inform user of success getting to this test. */
136 printf("Running Thread Stack Checking Test.................................. ");
137
138 /* Resume thread 1 to get the stack checking to take place. */
139 status = tx_thread_resume(&thread_1);
140
141 /* Suspend to allow thread 1 to run. */
142 tx_thread_suspend(&thread_0);
143
144 /* Terminate thread 1. */
145 status = tx_thread_terminate(&thread_1);
146
147 /* Check error code. */
148 #ifdef TX_ENABLE_STACK_CHECKING
149 if ((status != TX_SUCCESS) || (thread_1_counter != 1) || (thread_2_counter != 0) || (stack_error != 1))
150 #else
151 if ((status != TX_SUCCESS) || (thread_1_counter != 1) || (thread_2_counter != 0) || (stack_error != 0))
152 #endif
153 {
154
155 /* Thread error. */
156 printf("ERROR #5\n");
157 test_control_return(1);
158 }
159 else
160 {
161
162 /* Success! */
163 printf("SUCCESS!\n");
164 test_control_return(0);
165 }
166 }
167
168
thread_1_entry(ULONG thread_input)169 static void thread_1_entry(ULONG thread_input)
170 {
171
172 TX_THREAD fake_thread;
173
174 /* Call stack analyze with a NULL pointer. */
175 _tx_thread_stack_analyze(TX_NULL);
176
177 /* Call the stack analyze with a fake stack just to test that path. */
178 fake_thread.tx_thread_id = 0;
179 _tx_thread_stack_analyze(&fake_thread);
180
181 /* Call the stack analyze with a NULL stack pointer. */
182 fake_thread.tx_thread_id = ((ULONG) 0x54485244);
183 fake_thread.tx_thread_stack_start = TX_NULL;
184 _tx_thread_stack_analyze(&fake_thread);
185
186 /* Call the stack analyze with a NULL highest stack pointer. */
187 fake_thread.tx_thread_id = ((ULONG) 0x54485244);
188 fake_thread.tx_thread_stack_start = (void *) 0x1000;
189 fake_thread.tx_thread_stack_highest_ptr = TX_NULL;
190 _tx_thread_stack_analyze(&fake_thread);
191
192 /* Clear the pattern in thread 2's stack. */
193 TX_MEMSET(thread_2_stack_start, (CHAR) 0x11, TEST_STACK_SIZE_PRINTF);
194
195 /* Resume thread 2, which should cause the stack error to occur. */
196 tx_thread_resume(&thread_2);
197
198 /* Suspend thread 2. */
199 tx_thread_suspend(&thread_2);
200
201 /* Increment thread 1 counter. */
202 thread_1_counter++;
203
204 /* Now, deregister the stack error handler and get into a spin condition. We will then
205 want to terminate thread 1 from thread 0 when it awakes! */
206 tx_thread_stack_error_notify(TX_NULL);
207
208 /* Now resume thread 2 again to cause the stack error! */
209 tx_thread_resume(&thread_2);
210
211 /* Now suspend thread 2 again. */
212 tx_thread_suspend(&thread_2);
213
214 /* Resume thread 0. */
215 tx_thread_resume(&thread_0);
216 }
217
218
thread_2_entry(ULONG thread_input)219 static void thread_2_entry(ULONG thread_input)
220 {
221
222 /* Increment thread 1 counter. */
223 thread_2_counter++;
224 }
225