1 /* This test is designed to test for simultaneous thread event flag set AND ISR event flag set and clear. */
2
3 #include <stdio.h>
4 #include "tx_api.h"
5
6
7 /* Define the ISR dispatch. */
8
9 extern VOID (*test_isr_dispatch)(void);
10
11
12 /* Prototype for test control return. */
13 void test_control_return(UINT status);
14
15
16 static unsigned long thread_0_counter = 0;
17 static TX_THREAD thread_0;
18
19 static unsigned long thread_1_counter = 0;
20 static TX_THREAD thread_1;
21
22 static unsigned long thread_2_counter = 0;
23 static TX_THREAD thread_2;
24
25 static unsigned long timer_0_counter = 0;
26 static TX_TIMER timer_0;
27
28 static unsigned long event_flags_set_counter = 0;
29 static unsigned long condition_count = 0;
30
31 static TX_EVENT_FLAGS_GROUP event_flags_0;
32
33 extern UINT _tx_thread_preempt_disable;
34 extern UINT _tx_timer_system_clock;
35
36
37 /* Define thread prototypes. */
38
39 static void thread_0_entry(ULONG thread_input);
40 static void thread_1_entry(ULONG thread_input);
41 static void thread_2_entry(ULONG thread_input);
42 static void timer_0_entry(ULONG timer_input);
43
44
event_set_notify(TX_EVENT_FLAGS_GROUP * group)45 static void event_set_notify(TX_EVENT_FLAGS_GROUP *group)
46 {
47
48 /* Not necessary to do anything in this function. */
49 }
50
51
test_isr(void)52 static void test_isr(void)
53 {
54
55 UINT status;
56 ULONG actual;
57 static volatile UINT miss_count = 0;
58
59
60 /* Determine if the interrupt occurred when the preempt disable flag was set. */
61 if (_tx_thread_preempt_disable)
62 {
63
64 /* Yes this is the condition we are looking for, increment the test condition counter. */
65 condition_count++;
66 }
67
68 /*
69 It is possible for this test to get into a resonance condition in which
70 the ISR never occurs while preemption is disabled (especially if the
71 ISR is installed in the periodic timer interrupt handler, which is
72 conveniently available). Detect this condition and break out of it by
73 perturbing the duration of this ISR a pseudo-random amount of time.
74 */
75 else if (++miss_count > 100)
76 {
77 for (miss_count = _tx_timer_system_clock % 100; miss_count != 0; --miss_count);
78 }
79
80 if (((event_flags_0.tx_event_flags_group_current & 0x3) == 0) &&
81 (event_flags_0.tx_event_flags_group_suspended_count == 2))
82 {
83
84 /* Put the event_flags to wakeup thread 0. */
85 status = tx_event_flags_set(&event_flags_0, 0x3, TX_OR);
86
87 /* Clear the same flags immediately. */
88 status += tx_event_flags_set(&event_flags_0, 0xFFFFFFFC, TX_AND);
89
90 /* Setup some event flags just so we can clear them. */
91 status += tx_event_flags_set(&event_flags_0, 0x30000, TX_OR);
92
93 /* Clear the same flags immediately. */
94 status += tx_event_flags_set(&event_flags_0, 0xFFFEFFFF, TX_AND);
95
96 /* Clear the same flags immediately. */
97 status += tx_event_flags_set(&event_flags_0, 0xFFFDFFFC, TX_AND);
98
99 /* Check for an error. */
100 if (status)
101 return;
102
103 /* Get the events from an ISR. */
104 status = tx_event_flags_get(&event_flags_0, 0x30000, TX_OR, &actual, TX_NO_WAIT);
105
106 /* Check to make sure this results in an error. */
107 if (status != TX_NO_EVENTS)
108 return;
109
110 /* Do a set and a get consume from an ISR. */
111 status = tx_event_flags_set(&event_flags_0, 0x000000C0, TX_OR);
112
113 status += tx_event_flags_get(&event_flags_0, 0x00000080, TX_OR, &actual, TX_NO_WAIT);
114
115 status += tx_event_flags_get(&event_flags_0, 0x000000C0, TX_OR_CLEAR, &actual, TX_NO_WAIT);
116
117 /* Increment the event_flags counter. */
118 if ((status == TX_SUCCESS) && (actual == 0xC4))
119 {
120 event_flags_set_counter++;
121 }
122 }
123 }
124
125
126 /* Define what the initial system looks like. */
127
128 #ifdef CTEST
test_application_define(void * first_unused_memory)129 void test_application_define(void *first_unused_memory)
130 #else
131 void threadx_event_flag_isr_set_clear_application_define(void *first_unused_memory)
132 #endif
133 {
134
135 UINT status;
136 CHAR *pointer;
137
138
139 /* Put first available memory address into a character pointer. */
140 pointer = (CHAR *) first_unused_memory;
141
142 /* Put system definition stuff in here, e.g. thread creates and other assorted
143 create information. */
144
145 status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2,
146 pointer, TEST_STACK_SIZE_PRINTF,
147 17, 17, 100, TX_AUTO_START);
148 pointer = pointer + TEST_STACK_SIZE_PRINTF;
149
150 /* Check for status. */
151 if (status != TX_SUCCESS)
152 {
153
154 printf("Running Event Flag Set/Clear from ISR Test.......................... ERROR #1\n");
155 test_control_return(1);
156 }
157
158 status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1,
159 pointer, TEST_STACK_SIZE_PRINTF,
160 17, 17, 100, TX_AUTO_START);
161 pointer = pointer + TEST_STACK_SIZE_PRINTF;
162
163 /* Check for status. */
164 if (status != TX_SUCCESS)
165 {
166
167 printf("Running Event Flag Set/Clear from ISR Test.......................... ERROR #2\n");
168 test_control_return(1);
169 }
170
171 status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1,
172 pointer, TEST_STACK_SIZE_PRINTF,
173 17, 17, 100, TX_AUTO_START);
174 pointer = pointer + TEST_STACK_SIZE_PRINTF;
175
176 /* Check for status. */
177 if (status != TX_SUCCESS)
178 {
179
180 printf("Running Event Flag Set/Clear from ISR Test.......................... ERROR #3\n");
181 test_control_return(1);
182 }
183
184 /* Create event flags group. */
185 status = tx_event_flags_create(&event_flags_0, "event_flags 0");
186
187 /* Check for status. */
188 if (status != TX_SUCCESS)
189 {
190
191 printf("Running Event Flag Set/Clear from ISR Test.......................... ERROR #4\n");
192 test_control_return(1);
193 }
194
195 /* Create a timer to ensure a context save is called for every interrupt. */
196 status = tx_timer_create(&timer_0, "timer 0", timer_0_entry, 0, 1, 1, TX_AUTO_ACTIVATE);
197
198 /* Check for status. */
199 if (status != TX_SUCCESS)
200 {
201
202 printf("Running Event Flag Set/Clear from ISR Test.......................... ERROR #5\n");
203 test_control_return(1);
204 }
205
206 /* Register the event set notify function. */
207 status = tx_event_flags_set_notify(&event_flags_0, event_set_notify);
208
209 #ifndef TX_DISABLE_NOTIFY_CALLBACKS
210
211 /* Check status. */
212 if (status != TX_SUCCESS)
213 {
214
215 printf("Running Event Flag Set/Clear from ISR Test.......................... ERROR #6\n");
216 test_control_return(1);
217 }
218 #else
219
220 /* Check status. */
221 if (status != TX_FEATURE_NOT_ENABLED)
222 {
223
224 printf("Running Event Flag Set/Clear from ISR Test.......................... ERROR #7\n");
225 test_control_return(1);
226 }
227
228 #endif
229 }
230
231
232
233 /* Define the test threads. */
234
thread_0_entry(ULONG thread_input)235 static void thread_0_entry(ULONG thread_input)
236 {
237
238 UINT status;
239 ULONG actual;
240
241
242 /* Inform user. */
243 printf("Running Event Flag Set/Clear from ISR Test.......................... ");
244
245 /* Setup the test ISR. */
246 test_isr_dispatch = test_isr;
247
248 /* Loop to exploit the probability window inside tx_event_flags_set call. */
249 while (condition_count < 40)
250 {
251
252 /* Suspend on the event_flags that is going to be set via the ISR. */
253 status = tx_event_flags_get(&event_flags_0, 2, TX_OR_CLEAR, &actual, 4);
254
255 /* Determine if we have an unexpected result. */
256 if (status != TX_SUCCESS)
257 {
258
259 /* Test error! */
260 printf("ERROR #8\n");
261 test_control_return(1);
262 }
263
264 /* Check for the preempt disable flag being set. */
265 if (_tx_thread_preempt_disable)
266 {
267
268 /* Test error! */
269 printf("ERROR #9\n");
270 test_control_return(2);
271 }
272
273 /* Determine if we really got the event_flags. */
274 if (status == TX_SUCCESS)
275 {
276
277 /* Increment the thread count. */
278 thread_0_counter++;
279 }
280 }
281
282 /* Setup the test ISR. */
283 test_isr_dispatch = TX_NULL;
284
285 /* Let the other threads run once more... */
286 tx_thread_relinquish();
287
288 /* At this point, check to see if we got all the event_flagss! */
289 if ((thread_0_counter != event_flags_set_counter) ||
290 (thread_1_counter != event_flags_set_counter))
291 {
292
293 /* Test error! */
294 printf("ERROR #10\n");
295 test_control_return(3);
296 }
297 else
298 {
299
300 /* Successful test. */
301 printf("SUCCESS!\n");
302 test_control_return(0);
303 }
304 }
305
306
thread_1_entry(ULONG thread_input)307 static void thread_1_entry(ULONG thread_input)
308 {
309
310 UINT status;
311 ULONG actual;
312
313
314 /* Loop to exploit the probability window inside tx_event_flags_set call. */
315 while (1)
316 {
317
318 /* Suspend on the event_flags that is going to be set via the ISR. */
319 status = tx_event_flags_get(&event_flags_0, 1, TX_OR_CLEAR, &actual, 4);
320
321 /* Determine if we have an unexpected result. */
322 if (status != TX_SUCCESS)
323 {
324
325 break;
326 }
327
328 /* Increment this thread's counter. */
329 thread_1_counter++;
330 }
331 }
332
333
thread_2_entry(ULONG thread_input)334 static void thread_2_entry(ULONG thread_input)
335 {
336
337 /* Loop forever! */
338 while(1)
339 {
340
341
342 /* Set event flags - not the one needed by threads 0 and 1. */
343 tx_event_flags_set(&event_flags_0, 0x4, TX_OR);
344
345 /* Increment the thread counter. */
346 thread_2_counter++;
347
348 /* Let thread 0 run again! */
349 tx_thread_relinquish();
350 }
351 }
352
353
timer_0_entry(ULONG input)354 static void timer_0_entry(ULONG input)
355 {
356 timer_0_counter++;
357 }
358
359
360