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 #define TX_THREAD_SMP_SOURCE_CODE
25 
26 
27 /* Include necessary system files.  */
28 
29 #include "tx_api.h"
30 #include "tx_trace.h"
31 #include "tx_thread.h"
32 
33 
34 /**************************************************************************/
35 /*                                                                        */
36 /*  FUNCTION                                               RELEASE        */
37 /*                                                                        */
38 /*    _tx_thread_suspend                                 PORTABLE SMP     */
39 /*                                                           6.1          */
40 /*  AUTHOR                                                                */
41 /*                                                                        */
42 /*    William E. Lamie, Microsoft Corporation                             */
43 /*                                                                        */
44 /*  DESCRIPTION                                                           */
45 /*                                                                        */
46 /*    This function handles application suspend requests.  If the suspend */
47 /*    requires actual processing, this function calls the actual suspend  */
48 /*    thread routine.                                                     */
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_thread_system_suspend         Actual thread suspension          */
61 /*    _tx_thread_system_ni_suspend      Non-interruptable suspend thread  */
62 /*                                                                        */
63 /*  CALLED BY                                                             */
64 /*                                                                        */
65 /*    Application code                                                    */
66 /*                                                                        */
67 /*  RELEASE HISTORY                                                       */
68 /*                                                                        */
69 /*    DATE              NAME                      DESCRIPTION             */
70 /*                                                                        */
71 /*  09-30-2020     William E. Lamie         Initial Version 6.1           */
72 /*                                                                        */
73 /**************************************************************************/
_tx_thread_suspend(TX_THREAD * thread_ptr)74 UINT  _tx_thread_suspend(TX_THREAD *thread_ptr)
75 {
76 
77 TX_INTERRUPT_SAVE_AREA
78 
79 TX_THREAD  *current_thread;
80 UINT        status;
81 UINT        core_index;
82 
83 
84     /* Lockout interrupts while the thread is being suspended.  */
85     TX_DISABLE
86 
87     /* Pickup thread pointer.  */
88     TX_THREAD_GET_CURRENT(current_thread)
89 
90     /* If trace is enabled, insert this event into the trace buffer.  */
91     TX_TRACE_IN_LINE_INSERT(TX_TRACE_THREAD_SUSPEND_API, thread_ptr, thread_ptr -> tx_thread_state, TX_POINTER_TO_ULONG_CONVERT(&status), 0, TX_TRACE_THREAD_EVENTS)
92 
93     /* Log this kernel call.  */
94     TX_EL_THREAD_SUSPEND_INSERT
95 
96     /* Check the specified thread's current status.  */
97     if (thread_ptr -> tx_thread_state == TX_READY)
98     {
99 
100         /* Initialize status to success.  */
101         status =  TX_SUCCESS;
102 
103         /* Pickup the index.  */
104         core_index =  TX_SMP_CORE_ID;
105 
106         /* Determine if we are in a thread context.  */
107         if (_tx_thread_system_state[core_index] == ((ULONG) 0))
108         {
109 
110             /* Yes, we are in a thread context.  */
111 
112             /* Determine if the current thread is also the suspending thread.  */
113             if (current_thread == thread_ptr)
114             {
115 
116                 /* Determine if the preempt disable flag is non-zero.  */
117                 if (_tx_thread_preempt_disable != ((UINT) 0))
118                 {
119 
120                     /* Thread is terminated or completed.  */
121                     status =  TX_SUSPEND_ERROR;
122                 }
123             }
124         }
125 
126         /* Determine if the status is still successful.  */
127         if (status == TX_SUCCESS)
128         {
129 
130             /* Set the state to suspended.  */
131             thread_ptr -> tx_thread_state =    TX_SUSPENDED;
132 
133 #ifdef TX_NOT_INTERRUPTABLE
134 
135             /* Call actual non-interruptable thread suspension routine.  */
136             _tx_thread_system_ni_suspend(thread_ptr, ((ULONG) 0));
137 
138             /* Restore interrupts.  */
139             TX_RESTORE
140 #else
141 
142             /* Set the suspending flag. */
143             thread_ptr -> tx_thread_suspending =  TX_TRUE;
144 
145             /* Setup for no timeout period.  */
146             thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks =  ((ULONG) 0);
147 
148             /* Temporarily disable preemption.  */
149             _tx_thread_preempt_disable++;
150 
151             /* Restore interrupts.  */
152             TX_RESTORE
153 
154             /* Call actual thread suspension routine.  */
155             _tx_thread_system_suspend(thread_ptr);
156 #endif
157 
158 #ifdef TX_MISRA_ENABLE
159 
160             /* Disable interrupts.  */
161             TX_DISABLE
162 
163             /* Return success.  */
164             status =  TX_SUCCESS;
165 #else
166 
167             /* If MISRA is not enabled, return directly.  */
168             return(TX_SUCCESS);
169 #endif
170         }
171     }
172     else if (thread_ptr -> tx_thread_state == TX_TERMINATED)
173     {
174 
175         /* Thread is terminated.  */
176         status =  TX_SUSPEND_ERROR;
177     }
178     else if (thread_ptr -> tx_thread_state == TX_COMPLETED)
179     {
180 
181         /* Thread is completed.  */
182         status =  TX_SUSPEND_ERROR;
183     }
184     else if (thread_ptr -> tx_thread_state == TX_SUSPENDED)
185     {
186 
187         /* Already suspended, just set status to success.  */
188         status =  TX_SUCCESS;
189     }
190     else
191     {
192 
193         /* Just set the delayed suspension flag.  */
194         thread_ptr -> tx_thread_delayed_suspend =  TX_TRUE;
195 
196         /* Set status to success.  */
197         status =  TX_SUCCESS;
198     }
199 
200     /* Restore interrupts.  */
201     TX_RESTORE
202 
203     /* Always return success, since this function does not perform error
204        checking.  */
205     return(status);
206 }
207 
208