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