1 /**************************************************************************/
2 /*                                                                        */
3 /*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4 /*                                                                        */
5 /*       This software is licensed under the Microsoft Software License   */
6 /*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7 /*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8 /*       and in the root directory of this software.                      */
9 /*                                                                        */
10 /**************************************************************************/
11 
12 
13 /**************************************************************************/
14 /**************************************************************************/
15 /**                                                                       */
16 /** ThreadX Component                                                     */
17 /**                                                                       */
18 /**   Thread                                                              */
19 /**                                                                       */
20 /**************************************************************************/
21 /**************************************************************************/
22 
23 #define TX_SOURCE_CODE
24 
25 
26 /* Include necessary system files.  */
27 
28 #include "tx_api.h"
29 #include "tx_trace.h"
30 #include "tx_thread.h"
31 #include "tx_timer.h"
32 
33 
34 /**************************************************************************/
35 /*                                                                        */
36 /*  FUNCTION                                               RELEASE        */
37 /*                                                                        */
38 /*    _tx_thread_terminate                                PORTABLE C      */
39 /*                                                           6.1          */
40 /*  AUTHOR                                                                */
41 /*                                                                        */
42 /*    William E. Lamie, Microsoft Corporation                             */
43 /*                                                                        */
44 /*  DESCRIPTION                                                           */
45 /*                                                                        */
46 /*    This function handles application thread terminate requests.  Once  */
47 /*    a thread is terminated, it cannot be executed again unless it is    */
48 /*    deleted and recreated.                                              */
49 /*                                                                        */
50 /*  INPUT                                                                 */
51 /*                                                                        */
52 /*    thread_ptr                            Pointer to thread to suspend  */
53 /*                                                                        */
54 /*  OUTPUT                                                                */
55 /*                                                                        */
56 /*    status                                Return completion status      */
57 /*                                                                        */
58 /*  CALLS                                                                 */
59 /*                                                                        */
60 /*    _tx_timer_system_deactivate           Timer deactivate function     */
61 /*    _tx_thread_system_suspend             Actual thread suspension      */
62 /*    _tx_thread_system_ni_suspend          Non-interruptable suspend     */
63 /*                                            thread                      */
64 /*    _tx_thread_system_preempt_check       Check for preemption          */
65 /*    Suspend Cleanup Routine               Suspension cleanup function   */
66 /*                                                                        */
67 /*  CALLED BY                                                             */
68 /*                                                                        */
69 /*    Application code                                                    */
70 /*                                                                        */
71 /*  RELEASE HISTORY                                                       */
72 /*                                                                        */
73 /*    DATE              NAME                      DESCRIPTION             */
74 /*                                                                        */
75 /*  05-19-2020     William E. Lamie         Initial Version 6.0           */
76 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
77 /*                                            resulting in version 6.1    */
78 /*                                                                        */
79 /**************************************************************************/
_tx_thread_terminate(TX_THREAD * thread_ptr)80 UINT  _tx_thread_terminate(TX_THREAD *thread_ptr)
81 {
82 
83 TX_INTERRUPT_SAVE_AREA
84 
85 VOID        (*suspend_cleanup)(struct TX_THREAD_STRUCT *suspend_thread_ptr, ULONG suspension_sequence);
86 #ifndef TX_DISABLE_NOTIFY_CALLBACKS
87 VOID        (*entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT id);
88 #endif
89 UINT        status;
90 ULONG       suspension_sequence;
91 
92 
93     /* Default to successful completion.  */
94     status =  TX_SUCCESS;
95 
96     /* Lockout interrupts while the thread is being terminated.  */
97     TX_DISABLE
98 
99     /* Deactivate thread timer, if active.  */
100     _tx_timer_system_deactivate(&thread_ptr -> tx_thread_timer);
101 
102     /* If trace is enabled, insert this event into the trace buffer.  */
103     TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_TERMINATE, thread_ptr, thread_ptr -> tx_thread_state, TX_POINTER_TO_ULONG_CONVERT(&suspend_cleanup), 0, TX_TRACE_THREAD_EVENTS)
104 
105     /* Log this kernel call.  */
106     TX_EL_THREAD_TERMINATE_INSERT
107 
108     /* Is the thread already terminated?  */
109     if (thread_ptr -> tx_thread_state == TX_TERMINATED)
110     {
111 
112         /* Restore interrupts.  */
113         TX_RESTORE
114 
115         /* Return success since thread is already terminated.  */
116         status =  TX_SUCCESS;
117     }
118 
119     /* Check the specified thread's current status.  */
120     else if (thread_ptr -> tx_thread_state != TX_COMPLETED)
121     {
122 
123         /* Disable preemption.  */
124         _tx_thread_preempt_disable++;
125 
126 #ifndef TX_DISABLE_NOTIFY_CALLBACKS
127 
128         /* Pickup the entry/exit application callback routine.  */
129         entry_exit_notify =  thread_ptr -> tx_thread_entry_exit_notify;
130 #endif
131 
132         /* Check to see if the thread is currently ready.  */
133         if (thread_ptr -> tx_thread_state == TX_READY)
134         {
135 
136             /* Set the state to terminated.  */
137             thread_ptr -> tx_thread_state =  TX_TERMINATED;
138 
139             /* Thread state change.  */
140             TX_THREAD_STATE_CHANGE(thread_ptr, TX_TERMINATED)
141 
142 #ifdef TX_NOT_INTERRUPTABLE
143 
144 #ifndef TX_DISABLE_NOTIFY_CALLBACKS
145 
146             /* Determine if an application callback routine is specified.  */
147             if (entry_exit_notify != TX_NULL)
148             {
149 
150                 /* Yes, notify application that this thread has exited!  */
151                 (entry_exit_notify)(thread_ptr, TX_THREAD_EXIT);
152             }
153 #endif
154 
155             /* Call actual non-interruptable thread suspension routine.  */
156             _tx_thread_system_ni_suspend(thread_ptr, ((ULONG) 0));
157 #else
158 
159             /* Set the suspending flag.  */
160             thread_ptr -> tx_thread_suspending =  TX_TRUE;
161 
162             /* Setup for no timeout period.  */
163             thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks =  ((ULONG) 0);
164 
165             /* Disable preemption.  */
166             _tx_thread_preempt_disable++;
167 
168             /* Since the thread is currently ready, we don't need to
169                worry about calling the suspend cleanup routine!  */
170 
171             /* Restore interrupts.  */
172             TX_RESTORE
173 
174             /* Perform any additional activities for tool or user purpose.  */
175             TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
176 
177 #ifndef TX_DISABLE_NOTIFY_CALLBACKS
178 
179             /* Determine if an application callback routine is specified.  */
180             if (entry_exit_notify != TX_NULL)
181             {
182 
183                 /* Yes, notify application that this thread has exited!  */
184                 (entry_exit_notify)(thread_ptr, TX_THREAD_EXIT);
185             }
186 #endif
187 
188             /* Call actual thread suspension routine.  */
189             _tx_thread_system_suspend(thread_ptr);
190 
191             /* Disable interrupts.  */
192             TX_DISABLE
193 #endif
194         }
195         else
196         {
197 
198             /* Change the state to terminated.  */
199             thread_ptr -> tx_thread_state =    TX_TERMINATED;
200 
201             /* Thread state change.  */
202             TX_THREAD_STATE_CHANGE(thread_ptr, TX_TERMINATED)
203 
204             /* Set the suspending flag.  This prevents the thread from being
205                resumed before the cleanup routine is executed.  */
206             thread_ptr -> tx_thread_suspending =  TX_TRUE;
207 
208             /* Pickup the cleanup routine address.  */
209             suspend_cleanup =  thread_ptr -> tx_thread_suspend_cleanup;
210 
211 #ifndef TX_NOT_INTERRUPTABLE
212 
213             /* Pickup the suspension sequence number that is used later to verify that the
214                cleanup is still necessary.  */
215             suspension_sequence =  thread_ptr -> tx_thread_suspension_sequence;
216 #else
217 
218             /* When not interruptable is selected, the suspension sequence is not used - just set to 0.  */
219             suspension_sequence =  ((ULONG) 0);
220 #endif
221 
222 #ifndef TX_NOT_INTERRUPTABLE
223 
224             /* Restore interrupts.  */
225             TX_RESTORE
226 #endif
227 
228             /* Call any cleanup routines.  */
229             if (suspend_cleanup != TX_NULL)
230             {
231 
232                 /* Yes, there is a function to call.  */
233                 (suspend_cleanup)(thread_ptr, suspension_sequence);
234             }
235 
236 #ifndef TX_NOT_INTERRUPTABLE
237 
238             /* Disable interrupts.  */
239             TX_DISABLE
240 #endif
241 
242             /* Clear the suspending flag.  */
243             thread_ptr -> tx_thread_suspending =  TX_FALSE;
244 
245 #ifndef TX_NOT_INTERRUPTABLE
246 
247             /* Restore interrupts.  */
248             TX_RESTORE
249 #endif
250 
251             /* Perform any additional activities for tool or user purpose.  */
252             TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
253 
254 #ifndef TX_DISABLE_NOTIFY_CALLBACKS
255 
256             /* Determine if an application callback routine is specified.  */
257             if (entry_exit_notify != TX_NULL)
258             {
259 
260                 /* Yes, notify application that this thread has exited!  */
261                 (entry_exit_notify)(thread_ptr, TX_THREAD_EXIT);
262             }
263 #endif
264 
265 #ifndef TX_NOT_INTERRUPTABLE
266 
267             /* Disable interrupts.  */
268             TX_DISABLE
269 #endif
270         }
271 
272 #ifndef TX_NOT_INTERRUPTABLE
273 
274         /* Restore interrupts.  */
275         TX_RESTORE
276 #endif
277 
278         /* Determine if the application is using mutexes.  */
279         if (_tx_thread_mutex_release != TX_NULL)
280         {
281 
282             /* Yes, call the mutex release function via a function pointer that
283                is setup during initialization.  */
284             (_tx_thread_mutex_release)(thread_ptr);
285         }
286 
287 #ifndef TX_NOT_INTERRUPTABLE
288 
289         /* Disable interrupts.  */
290         TX_DISABLE
291 #endif
292 
293         /* Enable preemption.  */
294         _tx_thread_preempt_disable--;
295 
296         /* Restore interrupts.  */
297         TX_RESTORE
298     }
299     else
300     {
301 
302         /* Restore interrupts.  */
303         TX_RESTORE
304     }
305 
306     /* Check for preemption.  */
307     _tx_thread_system_preempt_check();
308 
309     /* Return completion status.  */
310     return(status);
311 }
312 
313