1 /* This test is designed to test the semaphore ceiling put. */
2
3 #include <stdio.h>
4 #include "tx_api.h"
5
6 static unsigned long thread_0_counter = 0;
7 static TX_THREAD thread_0;
8
9 static unsigned long thread_1_counter = 0;
10 static TX_THREAD thread_1;
11
12 static unsigned long thread_2_counter = 0;
13 static TX_THREAD thread_2;
14
15
16 static TX_SEMAPHORE semaphore_0;
17 static TX_SEMAPHORE semaphore_1;
18
19
20 /* Define thread prototypes. */
21
22 static void thread_0_entry(ULONG thread_input);
23 static void thread_1_entry(ULONG thread_input);
24 static void thread_2_entry(ULONG thread_input);
25
26
27 /* Prototype for test control return. */
28
29 void test_control_return(UINT status);
30
31
put_notify(TX_SEMAPHORE * semaphore_ptr)32 static void put_notify(TX_SEMAPHORE *semaphore_ptr)
33 {
34
35 /* Don't need to do anything in here... */
36 }
37
38
39 /* Define what the initial system looks like. */
40
41 #ifdef CTEST
test_application_define(void * first_unused_memory)42 void test_application_define(void *first_unused_memory)
43 #else
44 void threadx_semaphore_ceiling_put_application_define(void *first_unused_memory)
45 #endif
46 {
47
48 UINT status;
49 CHAR *pointer;
50
51
52 /* Put first available memory address into a character pointer. */
53 pointer = (CHAR *) first_unused_memory;
54
55 /* Put system definition stuff in here, e.g. thread creates and other assorted
56 create information. */
57
58 status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 1,
59 pointer, TEST_STACK_SIZE_PRINTF,
60 16, 16, 100, TX_AUTO_START);
61 pointer = pointer + TEST_STACK_SIZE_PRINTF;
62
63 /* Check for status. */
64 if (status != TX_SUCCESS)
65 {
66
67 printf("Running Semaphore Ceiling Put Test.................................. ERROR #1\n");
68 test_control_return(1);
69 }
70
71 status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1,
72 pointer, TEST_STACK_SIZE_PRINTF,
73 16, 16, 100, TX_AUTO_START);
74 pointer = pointer + TEST_STACK_SIZE_PRINTF;
75
76 /* Check for status. */
77 if (status != TX_SUCCESS)
78 {
79
80 printf("Running Semaphore Ceiling Put Test.................................. ERROR #2\n");
81 test_control_return(1);
82 }
83
84 status = tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2,
85 pointer, TEST_STACK_SIZE_PRINTF,
86 16, 16, 100, TX_DONT_START);
87 pointer = pointer + TEST_STACK_SIZE_PRINTF;
88
89 /* Check for status. */
90 if (status != TX_SUCCESS)
91 {
92
93 printf("Running Semaphore Ceiling Put Test.................................. ERROR #3\n");
94 test_control_return(1);
95 }
96
97 /* Create a semaphore with an initial count of 0. */
98 status = tx_semaphore_create(&semaphore_0, "semaphore 0", 0);
99 status += tx_semaphore_create(&semaphore_1, "semaphore 1", 0);
100
101 /* Check for status. */
102 if (status != TX_SUCCESS)
103 {
104
105 printf("Running Semaphore Ceiling Put Test.................................. ERROR #4\n");
106 test_control_return(1);
107 }
108
109 /* Setup the semaphore notify callback. */
110 status = tx_semaphore_put_notify(&semaphore_0, put_notify);
111
112 #ifndef TX_DISABLE_NOTIFY_CALLBACKS
113
114 /* Check for status. */
115 if (status != TX_SUCCESS)
116 {
117
118 printf("Running Semaphore Ceiling Put Test.................................. ERROR #5\n");
119 test_control_return(1);
120 }
121
122 #else
123
124 /* Check for status. */
125 if (status != TX_FEATURE_NOT_ENABLED)
126 {
127
128 printf("Running Semaphore Ceiling Put Test.................................. ERROR #6\n");
129 test_control_return(1);
130 }
131
132 #endif
133
134 }
135
136
137
138 /* Define the test threads. */
139
thread_0_entry(ULONG thread_input)140 static void thread_0_entry(ULONG thread_input)
141 {
142
143 UINT status;
144
145
146 /* Inform user. */
147 printf("Running Semaphore Ceiling Put Test.................................. ");
148
149 /* Increment thread 0 counter. */
150 thread_0_counter++;
151
152 /* Perform semaphore puts in order to exercise the ceiling put logic. */
153 status = tx_semaphore_ceiling_put(&semaphore_0, 2);
154 status += tx_semaphore_ceiling_put(&semaphore_0, 2);
155 status += tx_semaphore_ceiling_put(&semaphore_0, 2);
156 status += tx_semaphore_get(&semaphore_0, TX_NO_WAIT);
157 status += tx_semaphore_get(&semaphore_0, TX_NO_WAIT);
158
159 /* Check status. */
160 if (status != TX_CEILING_EXCEEDED)
161 {
162
163 /* Semaphore error. */
164 printf("ERROR #7\n");
165 test_control_return(1);
166 }
167
168 /* Relinquish to make the other thread suspend on the semaphore. */
169 tx_thread_relinquish();
170
171 /* Make sure the other thread has run. */
172 if (thread_1_counter != 1)
173 {
174
175 /* Semaphore error. */
176 printf("ERROR #8\n");
177 test_control_return(1);
178 }
179
180 /* Place an instance on the semaphore, this should resume the other thread
181 but not preempt this thread. */
182 status = tx_semaphore_ceiling_put(&semaphore_0, 2);
183
184 /* Check the status and the run counter of the other thread. */
185 if ((status != TX_SUCCESS) || (thread_1_counter != 1))
186 {
187
188 /* Semaphore error. */
189 printf("ERROR #9\n");
190 test_control_return(1);
191 }
192
193 /* Relinquish to allow the other thread to run. */
194 tx_thread_relinquish();
195
196 /* Make sure the other thread has run. */
197 if (thread_1_counter != 3)
198 {
199
200 /* Semaphore error. */
201 printf("ERROR #10\n");
202 test_control_return(1);
203 }
204
205 /* At this point, we need to resume thread 2 and relinquish in order to get that thread suspended on the
206 semaphore as well. */
207 tx_thread_resume(&thread_2);
208 tx_thread_relinquish();
209
210 /* Perform 2 semaphore put operations to resume both threads. */
211 status = tx_semaphore_ceiling_put(&semaphore_0, 2);
212 status += tx_semaphore_ceiling_put(&semaphore_0, 2);
213
214 /* Let both threads run again. */
215 tx_thread_relinquish();
216
217 /* Check the status and the run counter of the other thread. */
218 if ((status != TX_SUCCESS) || (thread_1_counter != 5) || (thread_2_counter != 3))
219 {
220
221 /* Semaphore error. */
222 printf("ERROR #11\n");
223 test_control_return(1);
224 }
225
226 /* Now turn off the semaphore notification. */
227 status = tx_semaphore_put_notify(&semaphore_0, TX_NULL);
228
229 #ifdef TX_DISABLE_NOTIFY_CALLBACKS
230
231 /* Clear the status since we know this feature is disabled and will return an error. */
232 status = TX_SUCCESS;
233 #endif
234
235 /* Put a semaphore on a semaphore that does not have suspension. */
236 status += tx_semaphore_ceiling_put(&semaphore_1, 2);
237
238 /* Repeat the semaphore ceiling put without notification process! */
239
240 /* Place an instance on the semaphore, this should resume the other thread
241 but not preempt this thread. */
242 status += tx_semaphore_ceiling_put(&semaphore_0, 2);
243
244 /* Check the status and the run counter of the other thread. */
245 if ((status != TX_SUCCESS) || (thread_1_counter != 5))
246 {
247
248 /* Semaphore error. */
249 printf("ERROR #9a\n");
250 test_control_return(1);
251 }
252
253 /* Relinquish to allow the other thread to run. */
254 tx_thread_relinquish();
255
256 /* Make sure the other thread has run. */
257 if (thread_1_counter != 7)
258 {
259
260 /* Semaphore error. */
261 printf("ERROR #10a\n");
262 test_control_return(1);
263 }
264
265 /* At this point, we need to resume thread 2 and relinquish in order to get that thread suspended on the
266 semaphore as well. */
267 tx_thread_resume(&thread_2);
268 tx_thread_relinquish();
269
270 /* Perform 2 semaphore put operations to resume both threads. */
271 status = tx_semaphore_ceiling_put(&semaphore_0, 2);
272 status += tx_semaphore_ceiling_put(&semaphore_0, 2);
273
274 /* Let both threads run again. */
275 tx_thread_relinquish();
276
277 /* Check the status and the run counter of the other thread. */
278 if ((status != TX_SUCCESS) || (thread_1_counter != 9) || (thread_2_counter != 5))
279 {
280
281 /* Semaphore error. */
282 printf("ERROR #11a\n");
283 test_control_return(1);
284 }
285 else
286 {
287
288 /* Successful test. */
289 printf("SUCCESS!\n");
290 test_control_return(0);
291 }
292 }
293
294
thread_1_entry(ULONG thread_input)295 static void thread_1_entry(ULONG thread_input)
296 {
297
298 UINT status;
299
300 while(1)
301 {
302
303 /* Increment thread run counter. */
304 thread_1_counter++;
305
306 /* Suspend on the semaphore. */
307 status = tx_semaphore_get(&semaphore_0, TX_WAIT_FOREVER);
308
309 /* Did we get the right status? */
310 if (status == TX_SUCCESS)
311 thread_1_counter++;
312 }
313 }
314
315
thread_2_entry(ULONG thread_input)316 static void thread_2_entry(ULONG thread_input)
317 {
318
319 UINT status;
320
321 while(1)
322 {
323
324 /* Increment thread run counter. */
325 thread_2_counter++;
326
327 /* Suspend on the semaphore. */
328 status = tx_semaphore_get(&semaphore_0, TX_WAIT_FOREVER);
329
330 /* Did we get the right status? */
331 if (status == TX_SUCCESS)
332 thread_2_counter++;
333 }
334 }
335