1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 
12 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /** ThreadX Component                                                     */
16 /**                                                                       */
17 /**   Thread                                                              */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 #define TX_SOURCE_CODE
23 #define TX_THREAD_SMP_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 
32 
33 /**************************************************************************/
34 /*                                                                        */
35 /*  FUNCTION                                               RELEASE        */
36 /*                                                                        */
37 /*    _tx_thread_suspend                                 PORTABLE SMP     */
38 /*                                                           6.1          */
39 /*  AUTHOR                                                                */
40 /*                                                                        */
41 /*    William E. Lamie, Microsoft Corporation                             */
42 /*                                                                        */
43 /*  DESCRIPTION                                                           */
44 /*                                                                        */
45 /*    This function handles application suspend requests.  If the suspend */
46 /*    requires actual processing, this function calls the actual suspend  */
47 /*    thread routine.                                                     */
48 /*                                                                        */
49 /*  INPUT                                                                 */
50 /*                                                                        */
51 /*    thread_ptr                            Pointer to thread to suspend  */
52 /*                                                                        */
53 /*  OUTPUT                                                                */
54 /*                                                                        */
55 /*    status                                Return completion status      */
56 /*                                                                        */
57 /*  CALLS                                                                 */
58 /*                                                                        */
59 /*    _tx_thread_system_suspend         Actual thread suspension          */
60 /*    _tx_thread_system_ni_suspend      Non-interruptable suspend thread  */
61 /*                                                                        */
62 /*  CALLED BY                                                             */
63 /*                                                                        */
64 /*    Application code                                                    */
65 /*                                                                        */
66 /*  RELEASE HISTORY                                                       */
67 /*                                                                        */
68 /*    DATE              NAME                      DESCRIPTION             */
69 /*                                                                        */
70 /*  09-30-2020     William E. Lamie         Initial Version 6.1           */
71 /*                                                                        */
72 /**************************************************************************/
_tx_thread_suspend(TX_THREAD * thread_ptr)73 UINT  _tx_thread_suspend(TX_THREAD *thread_ptr)
74 {
75 
76 TX_INTERRUPT_SAVE_AREA
77 
78 TX_THREAD  *current_thread;
79 UINT        status;
80 UINT        core_index;
81 
82 
83     /* Lockout interrupts while the thread is being suspended.  */
84     TX_DISABLE
85 
86     /* Pickup thread pointer.  */
87     TX_THREAD_GET_CURRENT(current_thread)
88 
89     /* If trace is enabled, insert this event into the trace buffer.  */
90     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)
91 
92     /* Log this kernel call.  */
93     TX_EL_THREAD_SUSPEND_INSERT
94 
95     /* Check the specified thread's current status.  */
96     if (thread_ptr -> tx_thread_state == TX_READY)
97     {
98 
99         /* Initialize status to success.  */
100         status =  TX_SUCCESS;
101 
102         /* Pickup the index.  */
103         core_index =  TX_SMP_CORE_ID;
104 
105         /* Determine if we are in a thread context.  */
106         if (_tx_thread_system_state[core_index] == ((ULONG) 0))
107         {
108 
109             /* Yes, we are in a thread context.  */
110 
111             /* Determine if the current thread is also the suspending thread.  */
112             if (current_thread == thread_ptr)
113             {
114 
115                 /* Determine if the preempt disable flag is non-zero.  */
116                 if (_tx_thread_preempt_disable != ((UINT) 0))
117                 {
118 
119                     /* Thread is terminated or completed.  */
120                     status =  TX_SUSPEND_ERROR;
121                 }
122             }
123         }
124 
125         /* Determine if the status is still successful.  */
126         if (status == TX_SUCCESS)
127         {
128 
129             /* Set the state to suspended.  */
130             thread_ptr -> tx_thread_state =    TX_SUSPENDED;
131 
132 #ifdef TX_NOT_INTERRUPTABLE
133 
134             /* Call actual non-interruptable thread suspension routine.  */
135             _tx_thread_system_ni_suspend(thread_ptr, ((ULONG) 0));
136 
137             /* Restore interrupts.  */
138             TX_RESTORE
139 #else
140 
141             /* Set the suspending flag. */
142             thread_ptr -> tx_thread_suspending =  TX_TRUE;
143 
144             /* Setup for no timeout period.  */
145             thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks =  ((ULONG) 0);
146 
147             /* Temporarily disable preemption.  */
148             _tx_thread_preempt_disable++;
149 
150             /* Restore interrupts.  */
151             TX_RESTORE
152 
153             /* Call actual thread suspension routine.  */
154             _tx_thread_system_suspend(thread_ptr);
155 #endif
156 
157 #ifdef TX_MISRA_ENABLE
158 
159             /* Disable interrupts.  */
160             TX_DISABLE
161 
162             /* Return success.  */
163             status =  TX_SUCCESS;
164 #else
165 
166             /* If MISRA is not enabled, return directly.  */
167             return(TX_SUCCESS);
168 #endif
169         }
170     }
171     else if (thread_ptr -> tx_thread_state == TX_TERMINATED)
172     {
173 
174         /* Thread is terminated.  */
175         status =  TX_SUSPEND_ERROR;
176     }
177     else if (thread_ptr -> tx_thread_state == TX_COMPLETED)
178     {
179 
180         /* Thread is completed.  */
181         status =  TX_SUSPEND_ERROR;
182     }
183     else if (thread_ptr -> tx_thread_state == TX_SUSPENDED)
184     {
185 
186         /* Already suspended, just set status to success.  */
187         status =  TX_SUCCESS;
188     }
189     else
190     {
191 
192         /* Just set the delayed suspension flag.  */
193         thread_ptr -> tx_thread_delayed_suspend =  TX_TRUE;
194 
195         /* Set status to success.  */
196         status =  TX_SUCCESS;
197     }
198 
199     /* Restore interrupts.  */
200     TX_RESTORE
201 
202     /* Always return success, since this function does not perform error
203        checking.  */
204     return(status);
205 }
206 
207