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