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