1 /* This test is designed to test the change preemption service call.  */
2 
3 #include   <stdio.h>
4 #include   "tx_api.h"
5 #include   "tx_thread.h"
6 #include   "tx_initialize.h"
7 
8 #ifndef TX_DISABLE_PREEMPTION_THRESHOLD
9 static unsigned long   thread_0_counter =  0;
10 static void    thread_1_entry(ULONG thread_input);
11 static void    thread_2_entry(ULONG thread_input);
12 
13 static unsigned long   thread_1_counter =  0;
14 static TX_THREAD       thread_1;
15 
16 static unsigned long   thread_2_counter =  0;
17 static TX_THREAD       thread_2;
18 
19 static TX_MUTEX        mutex_0;
20 #endif
21 
22 static TX_THREAD       thread_0;
23 
24 
25 /* Define thread prototypes.  */
26 
27 static void    thread_0_entry(ULONG thread_input);
28 
29 
30 /* Prototype for test control return.  */
31 
32 void  test_control_return(UINT status);
33 
34 
35 /* Define what the initial system looks like.  */
36 
37 #ifdef CTEST
test_application_define(void * first_unused_memory)38 void test_application_define(void *first_unused_memory)
39 #else
40 void    threadx_thread_preemption_change_application_define(void *first_unused_memory)
41 #endif
42 {
43 
44 UINT     status;
45 CHAR    *pointer;
46 
47 
48     /* Put first available memory address into a character pointer.  */
49     pointer =  (CHAR *) first_unused_memory;
50 
51     /* Put system definition stuff in here, e.g. thread creates and other assorted
52        create information.  */
53 
54     status =  tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1,
55             pointer, TEST_STACK_SIZE_PRINTF,
56             16, 15, TX_NO_TIME_SLICE, TX_AUTO_START);
57     pointer = pointer + TEST_STACK_SIZE_PRINTF;
58 
59     /* Check for status.  */
60     if (status != TX_SUCCESS)
61     {
62 
63         printf("Running Thread Preemption Change Test............................... ERROR #1\n");
64         test_control_return(1);
65     }
66 
67 #ifndef TX_DISABLE_PREEMPTION_THRESHOLD /* skip this test and pretend it passed */
68 
69     status =  tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1,
70             pointer, TEST_STACK_SIZE_PRINTF,
71             15, 15, TX_NO_TIME_SLICE, TX_AUTO_START);
72     pointer = pointer + TEST_STACK_SIZE_PRINTF;
73 
74     /* Check for status.  */
75     if (status != TX_SUCCESS)
76     {
77 
78         printf("Running Thread Preemption Change Test............................... ERROR #2\n");
79         test_control_return(1);
80     }
81 
82     status =  tx_thread_create(&thread_2, "thread 2", thread_2_entry, 1,
83             pointer, TEST_STACK_SIZE_PRINTF,
84             14, 14, TX_NO_TIME_SLICE, TX_DONT_START);
85     pointer = pointer + TEST_STACK_SIZE_PRINTF;
86 
87     /* Check for status.  */
88     if (status != TX_SUCCESS)
89     {
90 
91         printf("Running Thread Preemption Change Test............................... ERROR #3\n");
92         test_control_return(1);
93     }
94 
95     status =  tx_mutex_create(&mutex_0, "mutex 0", TX_INHERIT);
96 
97     /* Check for status.  */
98     if (status != TX_SUCCESS)
99     {
100 
101         printf("Running Thread Preemption Change Test............................... ERROR #4\n");
102         test_control_return(1);
103     }
104 #endif
105 }
106 
107 
108 
109 /* Define the test threads.  */
110 
thread_0_entry(ULONG thread_input)111 static void    thread_0_entry(ULONG thread_input)
112 {
113 
114 #ifndef TX_DISABLE_PREEMPTION_THRESHOLD
115 UINT    old_threshold;
116 UINT    status;
117 UINT    i;
118 #endif
119 
120 
121     /* Inform user.  */
122     printf("Running Thread Preemption Change Test............................... ");
123 
124 #ifndef TX_DISABLE_PREEMPTION_THRESHOLD /* skip this test and pretend it passed */
125 
126     /* Increment thread 0 counter.  */
127     thread_0_counter++;
128 
129     /* Resume thread 1, which has a higher priority.  Preemption is disabled
130        though so thread 1 should not run yet.  */
131     status =  tx_thread_resume(&thread_1);
132 
133     /* Check status and run counters of other threads.  */
134     if ((status != TX_SUCCESS) || (thread_1_counter != 0) || (thread_2_counter != 0))
135     {
136 
137         /* Thread error.  */
138         printf("ERROR #5\n");
139         test_control_return(1);
140     }
141 
142     /* Change the preemption-threshold such that thread 1 doesn't run yet... just for code coverage.  */
143     status =  tx_thread_preemption_change(&thread_0, 15, &old_threshold);
144 
145     /* Change the preemption threshold.  This should cause thread 1 to execute!  */
146     status +=  tx_thread_preemption_change(&thread_0, 16, &old_threshold);
147 
148     /* Check status and run counters of other threads.  */
149     if ((status != TX_SUCCESS) || (thread_1_counter != 1) || (thread_2_counter != 0) ||
150         (old_threshold != 15))
151     {
152 
153         /* Thread error.  */
154         printf("ERROR #6\n");
155         test_control_return(1);
156     }
157 
158     /* Change the preemption threshold of another thread.  */
159     status =  tx_thread_preemption_change(&thread_2, 11, &old_threshold);
160 
161     /* Check status and run counters of other threads.  */
162     if ((status != TX_SUCCESS) || (thread_1_counter != 1) || (thread_2_counter != 0) ||
163         (old_threshold != 14))
164     {
165 
166         /* Thread error.  */
167         printf("ERROR #7\n");
168         test_control_return(1);
169     }
170 
171     /* Change the preemption threshold back to 15.  */
172     status =  tx_thread_preemption_change(&thread_0, 15, &old_threshold);
173 
174     /* Check status and run counters of other threads.  */
175     if ((status != TX_SUCCESS) || (thread_1_counter != 1) || (thread_2_counter != 0) ||
176         (old_threshold != 16))
177     {
178 
179         /* Thread error.  */
180         printf("ERROR #8\n");
181         test_control_return(1);
182     }
183 
184     /* Resume thread 2.  This should preempt because it is priority 14 and the
185        current preemption threshold is 15.  */
186     status =  tx_thread_resume(&thread_2);
187 
188     /* Check status and run counters of other threads.  */
189     if ((status != TX_SUCCESS) || (thread_1_counter != 1) || (thread_2_counter != 1))
190     {
191 
192         /* Thread error.  */
193         printf("ERROR #9\n");
194         test_control_return(1);
195     }
196 
197     /* At this point, we are going to loop through preemption changes that result in
198        preemption.  */
199     for (i = 0; i < (TX_THREAD_EXECUTE_LOG_SIZE*3); i++)
200     {
201 
202         /* Change the preemption threshold back to 14.  */
203         status =  tx_thread_preemption_change(&thread_0, 14, &old_threshold);
204 
205         /* Check status.  */
206         if (status != TX_SUCCESS)
207         {
208 
209             /* Thread error.  */
210             printf("ERROR #10\n");
211             test_control_return(1);
212         }
213 
214         /* Resume thread 2 again.  */
215         status =  tx_thread_resume(&thread_2);
216 
217         /* Check status an thread 2 run counter.  */
218         if ((status != TX_SUCCESS) && (thread_2_counter != (i+1)))
219         {
220 
221             /* Thread error.  */
222             printf("ERROR #11\n");
223             test_control_return(1);
224         }
225 
226         /* Change the preemption threshold back to 15 to allow thread 2 to run.  */
227         status =  tx_thread_preemption_change(&thread_0, 15, &old_threshold);
228 
229         /* Check status an thread 2 run counter.  */
230         if ((status != TX_SUCCESS) && (thread_2_counter != (i+2)))
231         {
232 
233             /* Thread error.  */
234             printf("ERROR #12\n");
235             test_control_return(1);
236         }
237     }
238 
239     /* Change the priority of threads 0 and 1.  */
240     status =  tx_thread_priority_change(&thread_0, 7, &old_threshold);
241     status += tx_thread_priority_change(&thread_1, 5, &old_threshold);
242 
243     /* Check status.  */
244     if (status != TX_SUCCESS)
245     {
246 
247         /* Thread error.  */
248         printf("ERROR #13\n");
249         test_control_return(1);
250     }
251 
252     /* Change the preemption-threshold of this thread.  */
253     status =  tx_thread_preemption_change(&thread_0, 0, &old_threshold);
254 
255     /* Check status.  */
256     if ((status != TX_SUCCESS) || (old_threshold != 7))
257     {
258 
259         /* Thread error.  */
260         printf("ERROR #14\n");
261         test_control_return(1);
262     }
263 
264     /* Get the mutex that has priority inheritance.  */
265     status =  tx_mutex_get(&mutex_0, TX_WAIT_FOREVER);
266 
267     /* Check status.  */
268     if (status != TX_SUCCESS)
269     {
270 
271         /* Thread error.  */
272         printf("ERROR #15\n");
273         test_control_return(1);
274     }
275 
276     /* Resume thread 1 so that it can suspend on the mutex and automatically raise its priority.  */
277     tx_thread_resume(&thread_1);
278 
279     /* Self suspend so that thread 1 and run.  */
280     tx_thread_suspend(&thread_0);
281 
282     /* Restore the preemption-threshold of this thread.  */
283     status =  tx_thread_preemption_change(&thread_0, old_threshold, &old_threshold);
284 
285     /* Check status.  */
286     if ((status != TX_SUCCESS) || (old_threshold != 0) || (thread_0.tx_thread_priority != 5) || (thread_0.tx_thread_preempt_threshold != 5))
287     {
288 
289         /* Thread error.  */
290         printf("ERROR #16\n");
291         test_control_return(1);
292     }
293 
294     /* Ensure thread 0's entries in these lists were removed.  */
295     if (_tx_thread_preempted_maps[0] != 0 ||
296         _tx_thread_preemption_threshold_list[5] != TX_NULL)
297     {
298 
299         /* Thread error.  */
300         printf("ERROR #17\n");
301         test_control_return(1);
302     }
303 
304     /* Let thread 1 run again so it can release the mutex and undo the priority inheritance.  */
305     status =  tx_mutex_put(&mutex_0);
306 
307     /* Check status.  */
308     if ((status != TX_SUCCESS) || (thread_0.tx_thread_priority != 7) || (thread_0.tx_thread_preempt_threshold != 7))
309     {
310 
311         /* Thread error.  */
312         printf("ERROR #18\n");
313         test_control_return(1);
314     }
315 
316     /* Test direct call to the thread preemption change routine with a threshold greater than the current priority.  */
317     status =  _tx_thread_preemption_change(&thread_0, 8, &old_threshold);
318 
319     /* Check status.  */
320     if (status != TX_THRESH_ERROR)
321     {
322 
323         /* Thread error.  */
324         printf("ERROR #19\n");
325         test_control_return(1);
326     }
327 
328 #endif
329 
330     /* Successful test.  */
331     printf("SUCCESS!\n");
332     test_control_return(0);
333 
334 }
335 
336 #ifndef TX_DISABLE_PREEMPTION_THRESHOLD
thread_1_entry(ULONG thread_input)337 static void    thread_1_entry(ULONG thread_input)
338 {
339 
340 UINT old_threshold;
341 
342     /* Hit branch in _tx_thread_preemption_change where preemption-threshold is being disabled
343        but the thread doesn't have preemption-threshold.  */
344     tx_thread_preemption_change(&thread_1, 15, &old_threshold);
345 
346     /* Self suspend after initial run.  */
347     tx_thread_suspend(&thread_1);
348 
349     /* Increment the thread counter.  */
350     thread_1_counter++;
351 
352     /* Self suspend.  */
353     tx_thread_suspend(&thread_1);
354 
355     /* Resume thread 0.  */
356     tx_thread_resume(&thread_0);
357 
358     /* Get the mutex, which will cause suspension. */
359     tx_mutex_get(&mutex_0, TX_WAIT_FOREVER);
360 
361     /* Release the mutex.  */
362     tx_mutex_put(&mutex_0);
363 }
364 
365 
thread_2_entry(ULONG thread_input)366 static void    thread_2_entry(ULONG thread_input)
367 {
368 
369     while(1)
370     {
371 
372         /* Increment thread counter.  */
373         thread_2_counter++;
374 
375         /* Self suspend.  */
376         tx_thread_suspend(&thread_2);
377     }
378 }
379 #endif
380