1 /* This test is designed to test the semaphore suspension and another thread resuming the
2    same priority thread by doing a semaphore put.  */
3 
4 #include   <stdio.h>
5 #include   "tx_api.h"
6 
7 static unsigned long   thread_0_counter =  0;
8 static TX_THREAD       thread_0;
9 
10 static unsigned long   thread_1_counter =  0;
11 static TX_THREAD       thread_1;
12 
13 static unsigned long   thread_2_counter =  0;
14 static TX_THREAD       thread_2;
15 
16 
17 static TX_SEMAPHORE    semaphore_0;
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_non_preemption_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 Non Preemption 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 Non Preemption 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 Non Preemption 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 
100     /* Check for status.  */
101     if (status != TX_SUCCESS)
102     {
103 
104         printf("Running Semaphore Non Preemption Test............................... ERROR #4\n");
105         test_control_return(1);
106     }
107 
108     /* Setup the semaphore notify callback.  */
109     status =  tx_semaphore_put_notify(&semaphore_0, put_notify);
110 
111 #ifndef TX_DISABLE_NOTIFY_CALLBACKS
112 
113     /* Check for status.  */
114     if (status != TX_SUCCESS)
115     {
116 
117         printf("Running Semaphore Non Preemption Test............................... ERROR #5\n");
118         test_control_return(1);
119     }
120 
121 #else
122 
123     /* Check for status.  */
124     if (status != TX_FEATURE_NOT_ENABLED)
125     {
126 
127         printf("Running Semaphore Non Preemption Test............................... ERROR #6\n");
128         test_control_return(1);
129     }
130 
131 #endif
132 }
133 
134 
135 
136 /* Define the test threads.  */
137 
thread_0_entry(ULONG thread_input)138 static void    thread_0_entry(ULONG thread_input)
139 {
140 
141 UINT    status;
142 
143 
144     /* Inform user.  */
145     printf("Running Semaphore Non Preemption Test............................... ");
146 
147     /* Increment thread 0 counter.  */
148     thread_0_counter++;
149 
150     /* Perform a semaphore put and get, just to exercise the notify path of a non-resumption
151        semaphore put.  */
152     status =  tx_semaphore_put(&semaphore_0);
153     status += tx_semaphore_get(&semaphore_0, TX_NO_WAIT);
154 
155     /* Check status.  */
156     if (status != TX_SUCCESS)
157     {
158 
159         /* Semaphore error.  */
160         printf("ERROR #7\n");
161         test_control_return(1);
162     }
163 
164     /* Relinquish to make the other thread suspend on the semaphore.  */
165     tx_thread_relinquish();
166 
167     /* Make sure the other thread has run.  */
168     if (thread_1_counter != 1)
169     {
170 
171         /* Semaphore error.  */
172         printf("ERROR #8\n");
173         test_control_return(1);
174     }
175 
176     /* Place an instance on the semaphore, this should resume the other thread
177        but not preempt this thread.  */
178     status =  tx_semaphore_put(&semaphore_0);
179 
180     /* Check the status and the run counter of the other thread.  */
181     if ((status != TX_SUCCESS) || (thread_1_counter != 1))
182     {
183 
184         /* Semaphore error.  */
185         printf("ERROR #9\n");
186         test_control_return(1);
187     }
188 
189     /* Relinquish to allow the other thread to run.  */
190     tx_thread_relinquish();
191 
192     /* Make sure the other thread has run.  */
193     if (thread_1_counter != 3)
194     {
195 
196         /* Semaphore error.  */
197         printf("ERROR #10\n");
198         test_control_return(1);
199     }
200 
201     /* At this point, we need to resume thread 2 and relinquish in order to get that thread suspended on the
202        semaphore as well.  */
203     tx_thread_resume(&thread_2);
204     tx_thread_relinquish();
205 
206     /* Perform 2 semaphore put operations to resume both threads.  */
207     status =  tx_semaphore_put(&semaphore_0);
208     status += tx_semaphore_put(&semaphore_0);
209 
210     /* Let both threads run again.  */
211     tx_thread_relinquish();
212 
213     /* Check the status and the run counter of the other thread.  */
214     if ((status != TX_SUCCESS) || (thread_1_counter != 5) || (thread_2_counter != 3))
215     {
216 
217         /* Semaphore error.  */
218         printf("ERROR #11\n");
219         test_control_return(1);
220     }
221     else
222     {
223 
224         /* Successful test.  */
225         printf("SUCCESS!\n");
226         test_control_return(0);
227     }
228 }
229 
230 
thread_1_entry(ULONG thread_input)231 static void    thread_1_entry(ULONG thread_input)
232 {
233 
234 UINT    status;
235 
236     while(1)
237     {
238 
239         /* Increment thread run counter.  */
240         thread_1_counter++;
241 
242         /* Suspend on the semaphore. */
243         status =  tx_semaphore_get(&semaphore_0, TX_WAIT_FOREVER);
244 
245         /* Did we get the right status?  */
246         if (status == TX_SUCCESS)
247             thread_1_counter++;
248     }
249 }
250 
251 
thread_2_entry(ULONG thread_input)252 static void    thread_2_entry(ULONG thread_input)
253 {
254 
255 UINT    status;
256 
257     while(1)
258     {
259 
260         /* Increment thread run counter.  */
261         thread_2_counter++;
262 
263         /* Suspend on the semaphore. */
264         status =  tx_semaphore_get(&semaphore_0, TX_WAIT_FOREVER);
265 
266         /* Did we get the right status?  */
267         if (status == TX_SUCCESS)
268             thread_2_counter++;
269     }
270 }
271 
272