1 /* This test is designed to test the mutex suspension and timeout functionality. */
2
3 #include <stdio.h>
4 #include "tx_api.h"
5 #include "tx_thread.h"
6 #include "tx_mutex.h"
7
8
9 //static unsigned long thread_0_counter = 0;
10 static TX_THREAD thread_0;
11 static TX_THREAD thread_1;
12 static TX_THREAD thread_2;
13 static TX_THREAD thread_3;
14 static TX_THREAD thread_4;
15 static TX_THREAD low_priority;
16
17
18 static TX_MUTEX mutex_0;
19 static TX_MUTEX mutex_1;
20
21
22
23 /* Define thread prototypes. */
24
25 static void thread_0_entry(ULONG thread_input);
26 static void thread_1_entry(ULONG thread_input);
27 static void thread_2_entry(ULONG thread_input);
28 static void thread_3_entry(ULONG thread_input);
29 static void thread_4_entry(ULONG thread_input);
30 static void low_priority_entry(ULONG thread_input);
31
32
33 /* Prototype for test control return. */
34 extern void test_control_return(UINT status);
35
36
37 #ifndef TX_MANUAL_TEST
38
39 /* Define test flags for automated test. */
40
41 extern TEST_FLAG threadx_mutex_suspension_put_test;
42 extern TEST_FLAG threadx_mutex_suspension_priority_test;
43
44 #endif
45
46
47 /* This test routine is used to get NULL suspension lists in various parts of tx_mutex_put. This is hooked up to IRQ 0 on this simulation and is entered manually at the
48 correct time. */
abort_all_threads_suspended_on_mutex(void)49 void abort_all_threads_suspended_on_mutex(void)
50 {
51
52 TX_THREAD *thread_ptr;
53
54 thread_ptr = _tx_thread_created_ptr;
55 while (thread_ptr)
56 {
57 if (thread_ptr -> tx_thread_state == TX_MUTEX_SUSP)
58 tx_thread_wait_abort(thread_ptr);
59
60 thread_ptr = thread_ptr -> tx_thread_created_next;
61 if (thread_ptr == _tx_thread_created_ptr)
62 break;
63 }
64 }
65
66
67 /* This test routine is used to get a thread of a non ready state into _tx_mutex_change, called froim _tx_mutex_put. This is hooked up to IRQ 1 on this simulation and is entered manually at the
68 correct time. */
suspend_lowest_priority(void)69 void suspend_lowest_priority(void)
70 {
71
72 tx_thread_suspend(&low_priority);
73 }
74
75
76 /* Define what the initial system looks like. */
77
78 #ifdef CTEST
test_application_define(void * first_unused_memory)79 void test_application_define(void *first_unused_memory)
80 #else
81 void threadx_mutex_suspension_timeout_application_define(void *first_unused_memory)
82 #endif
83 {
84
85 UINT status;
86 CHAR *pointer;
87
88
89 /* Put first available memory address into a character pointer. */
90 pointer = (CHAR *) first_unused_memory;
91
92 /* Put system definition stuff in here, e.g. thread creates and other assorted
93 create information. */
94
95 status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,
96 pointer, TEST_STACK_SIZE_PRINTF,
97 16, 16, 100, TX_AUTO_START);
98 pointer = pointer + TEST_STACK_SIZE_PRINTF;
99 status += tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1,
100 pointer, TEST_STACK_SIZE_PRINTF,
101 1, 1, 100, TX_DONT_START);
102 pointer = pointer + TEST_STACK_SIZE_PRINTF;
103 status += tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2,
104 pointer, TEST_STACK_SIZE_PRINTF,
105 2, 2, 100, TX_DONT_START);
106 pointer = pointer + TEST_STACK_SIZE_PRINTF;
107 status += tx_thread_create(&thread_3, "thread 3", thread_3_entry, 3,
108 pointer, TEST_STACK_SIZE_PRINTF,
109 3, 3, 100, TX_DONT_START);
110 pointer = pointer + TEST_STACK_SIZE_PRINTF;
111 status += tx_thread_create(&thread_4, "thread 4", thread_4_entry, 4,
112 pointer, TEST_STACK_SIZE_PRINTF,
113 4, 4, 100, TX_DONT_START);
114 pointer = pointer + TEST_STACK_SIZE_PRINTF;
115 status += tx_thread_create(&low_priority, "low priority", low_priority_entry, 30,
116 pointer, TEST_STACK_SIZE_PRINTF,
117 30, 30, 100, TX_DONT_START);
118 pointer = pointer + TEST_STACK_SIZE_PRINTF;
119
120 /* Check for status. */
121 if (status != TX_SUCCESS)
122 {
123
124 printf("Running Mutex Suspension Timeout Test............................... ERROR #1\n");
125 test_control_return(1);
126 }
127
128 /* Create mutexes. */
129 status = tx_mutex_create(&mutex_0, "mutex 0", TX_NO_INHERIT);
130 status += tx_mutex_create(&mutex_1, "mutex 1", TX_INHERIT);
131
132 /* Check for status. */
133 if (status != TX_SUCCESS)
134 {
135
136 printf("Running Mutex Suspension Timeout Test............................... ERROR #2\n");
137 test_control_return(1);
138 }
139
140 /* Get the mutex to prevent thread from getting it. */
141 tx_mutex_get(&mutex_0, TX_NO_WAIT);
142 }
143
144
145
146 /* Define the test threads. */
147
thread_0_entry(ULONG thread_input)148 static void thread_0_entry(ULONG thread_input)
149 {
150
151 UINT status;
152 UINT old_preempt;
153 UINT old_priority;
154
155
156 /* Inform user. */
157 printf("Running Mutex Suspension Timeout Test............................... ");
158
159 /* Sleep for 2 ticks for fresh timer. */
160 tx_thread_sleep(2);
161
162 /* Set clock to 0. */
163 tx_time_set(0);
164
165 /* Suspend on the mutex. */
166 status = tx_mutex_get(&mutex_0, 33);
167
168 /* Did we get the right status at the right time? */
169 if ((status != TX_NOT_AVAILABLE) || (tx_time_get() != 33))
170 {
171
172 /* Mutex error. */
173 printf("ERROR #3\n");
174 test_control_return(1);
175 }
176
177 /* Get the mutex. */
178 status = tx_mutex_get(&mutex_1, TX_WAIT_FOREVER);
179
180 /* Make sure the three higher priority threads suspend on the mutex. */
181 tx_thread_resume(&thread_4);
182 tx_thread_resume(&thread_3);
183 tx_thread_resume(&thread_2);
184 tx_thread_resume(&thread_1);
185
186
187 #ifdef TX_MANUAL_TEST
188
189 /* Set BP hear and step into code and generate appropriate interrupt IRQ 0 by hand right after the prioritize function with interrupts enabled. This is to achieve the empty list branch coverage after the prioritize function. */
190 tx_mutex_put(&mutex_1);
191 #else
192
193 /* Set the flag such that generate the condition wehre the empty list condition is satisfied in the branch coverage. */
194 threadx_mutex_suspension_put_test = 1;
195 tx_mutex_put(&mutex_1);
196 #endif
197
198 /* Now some hand testing for tx_mutex_priority_change. */
199
200 /* Resume the low priority thread. */
201 tx_thread_resume(&low_priority);
202
203 /* Simulate a call from inside of mutex put, but doing it here makes life easier. */
204 _tx_thread_preempt_disable++;
205
206 #ifdef TX_MANUAL_TEST
207
208 /* Set BP here and step into code and step through the code until the internal thread resume function returns, then issue an IRQ 1 to cause an ISR to suspend the thread and test the first condition. */
209 _tx_mutex_priority_change(&low_priority, 30);
210 #else
211
212 /* Set the flag to suspend the thread and test the first condition after internal resume is called. */
213 threadx_mutex_suspension_priority_test = 1;
214 _tx_mutex_priority_change(&low_priority, 30);
215 #endif
216
217 /* Resume the low priority thread. */
218 tx_thread_resume(&low_priority);
219
220 /* Now call internal _tx_mutex_priority_change, this should test the preemption-threshold throw-away path. */
221 _tx_mutex_priority_change(&low_priority, 30);
222
223 /* Now make it so we can have a higher-priority thread ready but not the execute pointer because of preemption-threshold. */
224 tx_thread_preemption_change(&thread_0, 10, &old_preempt);
225 tx_thread_priority_change(&low_priority, 10, &old_priority);
226
227 /* Now call the internal mutex priority change on this thread to get the throw-away path on original priority being the same when execute ptr is different. */
228 _tx_thread_execute_ptr = &low_priority;
229 _tx_mutex_priority_change(&low_priority, 10);
230 _tx_thread_execute_ptr = &thread_0;
231
232 /* Now make the low priority thread lower again, but with a preemption-threshold equal to thread_0. This will test yet another throw away condition. */
233 low_priority.tx_thread_inherit_priority = ((UINT) TX_MAX_PRIORITIES);
234 tx_thread_priority_change(&low_priority, 30, &old_priority);
235 tx_thread_preemption_change(&low_priority, 10, &old_preempt);
236
237 /* Now call the internal mutex priority change on this thread with the same priority. */
238 _tx_mutex_priority_change(&low_priority, 30);
239 _tx_thread_preempt_disable--;
240
241 /* Successful test. */
242 printf("SUCCESS!\n");
243 test_control_return(0);
244 }
245
246
thread_1_entry(ULONG thread_input)247 static void thread_1_entry(ULONG thread_input)
248 {
249 UINT status;
250
251 /* Loop to get the mutex. */
252 while(1)
253 {
254
255 /* Get and release the mutex. */
256 status = tx_mutex_get(&mutex_1, TX_WAIT_FOREVER);
257 if (status == TX_SUCCESS)
258 tx_mutex_put(&mutex_1);
259 tx_thread_suspend(&thread_1);
260 }
261 }
262
263
thread_2_entry(ULONG thread_input)264 static void thread_2_entry(ULONG thread_input)
265 {
266
267 UINT status;
268
269 /* Loop to get the mutex. */
270 while(1)
271 {
272
273 /* Get and release the mutex. */
274 status = tx_mutex_get(&mutex_1, TX_WAIT_FOREVER);
275 if (status == TX_SUCCESS)
276 tx_mutex_put(&mutex_1);
277 tx_thread_suspend(&thread_2);
278 }
279 }
280
281
thread_3_entry(ULONG thread_input)282 static void thread_3_entry(ULONG thread_input)
283 {
284
285 UINT status;
286
287 /* Loop to get the mutex. */
288 while(1)
289 {
290
291 /* Get and release the mutex. */
292 status = tx_mutex_get(&mutex_1, TX_WAIT_FOREVER);
293 if (status == TX_SUCCESS)
294 tx_mutex_put(&mutex_1);
295 tx_thread_suspend(&thread_3);
296 }
297 }
298
thread_4_entry(ULONG thread_input)299 static void thread_4_entry(ULONG thread_input)
300 {
301
302 UINT status;
303
304 /* Loop to get the mutex. */
305 while(1)
306 {
307
308 /* Get and release the mutex. */
309 status = tx_mutex_get(&mutex_1, TX_WAIT_FOREVER);
310 if (status == TX_SUCCESS)
311 tx_mutex_put(&mutex_1);
312 tx_thread_suspend(&thread_4);
313 }
314 }
315
316
low_priority_entry(ULONG thread_input)317 static void low_priority_entry(ULONG thread_input)
318 {
319 }
320