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