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