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 /** Event Flags */
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_thread.h"
30 #include "tx_event_flags.h"
31
32
33 /**************************************************************************/
34 /* */
35 /* FUNCTION RELEASE */
36 /* */
37 /* _tx_event_flags_cleanup PORTABLE C */
38 /* 6.1 */
39 /* AUTHOR */
40 /* */
41 /* William E. Lamie, Microsoft Corporation */
42 /* */
43 /* DESCRIPTION */
44 /* */
45 /* This function processes event flags timeout and thread terminate */
46 /* actions that require the event flags data structures to be cleaned */
47 /* up. */
48 /* */
49 /* INPUT */
50 /* */
51 /* thread_ptr Pointer to suspended thread's */
52 /* control block */
53 /* */
54 /* OUTPUT */
55 /* */
56 /* None */
57 /* */
58 /* CALLS */
59 /* */
60 /* _tx_thread_system_resume Resume thread service */
61 /* _tx_thread_system_ni_resume Non-interruptable resume thread */
62 /* */
63 /* CALLED BY */
64 /* */
65 /* _tx_thread_timeout Thread timeout processing */
66 /* _tx_thread_terminate Thread terminate processing */
67 /* _tx_thread_wait_abort Thread wait abort processing */
68 /* */
69 /* RELEASE HISTORY */
70 /* */
71 /* DATE NAME DESCRIPTION */
72 /* */
73 /* 05-19-2020 William E. Lamie Initial Version 6.0 */
74 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
75 /* resulting in version 6.1 */
76 /* */
77 /**************************************************************************/
_tx_event_flags_cleanup(TX_THREAD * thread_ptr,ULONG suspension_sequence)78 VOID _tx_event_flags_cleanup(TX_THREAD *thread_ptr, ULONG suspension_sequence)
79 {
80
81 #ifndef TX_NOT_INTERRUPTABLE
82 TX_INTERRUPT_SAVE_AREA
83 #endif
84
85 TX_EVENT_FLAGS_GROUP *group_ptr;
86 UINT suspended_count;
87 TX_THREAD *suspension_head;
88 TX_THREAD *next_thread;
89 TX_THREAD *previous_thread;
90
91
92 #ifndef TX_NOT_INTERRUPTABLE
93
94 /* Disable interrupts to remove the suspended thread from the event flags group. */
95 TX_DISABLE
96
97 /* Determine if the cleanup is still required. */
98 if (thread_ptr -> tx_thread_suspend_cleanup == &(_tx_event_flags_cleanup))
99 {
100
101 /* Check for valid suspension sequence. */
102 if (suspension_sequence == thread_ptr -> tx_thread_suspension_sequence)
103 {
104
105 /* Setup pointer to event flags control block. */
106 group_ptr = TX_VOID_TO_EVENT_FLAGS_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block);
107
108 /* Check for a NULL event flags control block pointer. */
109 if (group_ptr != TX_NULL)
110 {
111
112 /* Is the group pointer ID valid? */
113 if (group_ptr -> tx_event_flags_group_id == TX_EVENT_FLAGS_ID)
114 {
115
116 /* Determine if there are any thread suspensions. */
117 if (group_ptr -> tx_event_flags_group_suspended_count != TX_NO_SUSPENSIONS)
118 {
119 #else
120
121 /* Setup pointer to event flags control block. */
122 group_ptr = TX_VOID_TO_EVENT_FLAGS_POINTER_CONVERT(thread_ptr -> tx_thread_suspend_control_block);
123 #endif
124
125 /* Yes, we still have thread suspension! */
126
127 /* Clear the suspension cleanup flag. */
128 thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
129
130 /* Pickup the suspended count. */
131 suspended_count = group_ptr -> tx_event_flags_group_suspended_count;
132
133 /* Pickup the suspension head. */
134 suspension_head = group_ptr -> tx_event_flags_group_suspension_list;
135
136 /* Determine if the cleanup is being done while a set operation was interrupted. If the
137 suspended count is non-zero and the suspension head is NULL, the list is being processed
138 and cannot be touched from here. The suspension list removal will instead take place
139 inside the event flag set code. */
140 if (suspension_head != TX_NULL)
141 {
142
143 /* Remove the suspended thread from the list. */
144
145 /* Decrement the local suspension count. */
146 suspended_count--;
147
148 /* Store the updated suspended count. */
149 group_ptr -> tx_event_flags_group_suspended_count = suspended_count;
150
151 /* See if this is the only suspended thread on the list. */
152 if (suspended_count == TX_NO_SUSPENSIONS)
153 {
154
155 /* Yes, the only suspended thread. */
156
157 /* Update the head pointer. */
158 group_ptr -> tx_event_flags_group_suspension_list = TX_NULL;
159 }
160 else
161 {
162
163 /* At least one more thread is on the same suspension list. */
164
165 /* Update the links of the adjacent threads. */
166 next_thread = thread_ptr -> tx_thread_suspended_next;
167 previous_thread = thread_ptr -> tx_thread_suspended_previous;
168 next_thread -> tx_thread_suspended_previous = previous_thread;
169 previous_thread -> tx_thread_suspended_next = next_thread;
170
171 /* Determine if we need to update the head pointer. */
172 if (suspension_head == thread_ptr)
173 {
174
175 /* Update the list head pointer. */
176 group_ptr -> tx_event_flags_group_suspension_list = next_thread;
177 }
178 }
179 }
180 else
181 {
182
183 /* In this case, the search pointer in an interrupted event flag set must be reset. */
184 group_ptr -> tx_event_flags_group_reset_search = TX_TRUE;
185 }
186
187 /* Now we need to determine if this cleanup is from a terminate, timeout,
188 or from a wait abort. */
189 if (thread_ptr -> tx_thread_state == TX_EVENT_FLAG)
190 {
191
192 /* Timeout condition and the thread still suspended on the event flags group.
193 Setup return error status and resume the thread. */
194
195 #ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
196
197 /* Increment the total timeouts counter. */
198 _tx_event_flags_performance_timeout_count++;
199
200 /* Increment the number of timeouts on this event flags group. */
201 group_ptr -> tx_event_flags_group____performance_timeout_count++;
202 #endif
203
204 /* Setup return status. */
205 thread_ptr -> tx_thread_suspend_status = TX_NO_EVENTS;
206
207 #ifdef TX_NOT_INTERRUPTABLE
208
209 /* Resume the thread! */
210 _tx_thread_system_ni_resume(thread_ptr);
211 #else
212
213 /* Temporarily disable preemption. */
214 _tx_thread_preempt_disable++;
215
216 /* Restore interrupts. */
217 TX_RESTORE
218
219 /* Resume the thread! Check for preemption even though we are executing
220 from the system timer thread right now which normally executes at the
221 highest priority. */
222 _tx_thread_system_resume(thread_ptr);
223
224 /* Disable interrupts. */
225 TX_DISABLE
226 #endif
227 }
228 #ifndef TX_NOT_INTERRUPTABLE
229 }
230 }
231 }
232 }
233 }
234
235 /* Restore interrupts. */
236 TX_RESTORE
237 #endif
238 }
239
240