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