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 /** Mutex */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define TX_SOURCE_CODE
23
24
25 /* Include necessary system files. */
26
27 #include "tx_api.h"
28 #include "tx_trace.h"
29 #include "tx_thread.h"
30 #include "tx_mutex.h"
31
32
33 /**************************************************************************/
34 /* */
35 /* FUNCTION RELEASE */
36 /* */
37 /* _tx_mutex_delete PORTABLE C */
38 /* 6.1 */
39 /* AUTHOR */
40 /* */
41 /* William E. Lamie, Microsoft Corporation */
42 /* */
43 /* DESCRIPTION */
44 /* */
45 /* This function deletes the specified mutex. All threads */
46 /* suspended on the mutex are resumed with the TX_DELETED status */
47 /* code. */
48 /* */
49 /* INPUT */
50 /* */
51 /* mutex_ptr Pointer to mutex control block */
52 /* */
53 /* OUTPUT */
54 /* */
55 /* TX_SUCCESS Successful completion status */
56 /* */
57 /* CALLS */
58 /* */
59 /* _tx_mutex_put Release an owned mutex */
60 /* _tx_thread_system_preempt_check Check for preemption */
61 /* _tx_thread_system_resume Resume thread service */
62 /* _tx_thread_system_ni_resume Non-interruptable resume thread */
63 /* */
64 /* CALLED BY */
65 /* */
66 /* Application Code */
67 /* */
68 /* RELEASE HISTORY */
69 /* */
70 /* DATE NAME DESCRIPTION */
71 /* */
72 /* 05-19-2020 William E. Lamie Initial Version 6.0 */
73 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
74 /* resulting in version 6.1 */
75 /* */
76 /**************************************************************************/
_tx_mutex_delete(TX_MUTEX * mutex_ptr)77 UINT _tx_mutex_delete(TX_MUTEX *mutex_ptr)
78 {
79
80 TX_INTERRUPT_SAVE_AREA
81
82 TX_THREAD *thread_ptr;
83 TX_THREAD *next_thread;
84 TX_THREAD *owner_thread;
85 UINT suspended_count;
86 TX_MUTEX *next_mutex;
87 TX_MUTEX *previous_mutex;
88 #ifdef TX_MISRA_ENABLE
89 UINT status;
90 #endif
91
92 /* Disable interrupts to remove the mutex from the created list. */
93 TX_DISABLE
94
95 /* If trace is enabled, insert this event into the trace buffer. */
96 TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_DELETE, mutex_ptr, TX_POINTER_TO_ULONG_CONVERT(&thread_ptr), 0, 0, TX_TRACE_MUTEX_EVENTS)
97
98 /* Optional mutex delete extended processing. */
99 TX_MUTEX_DELETE_EXTENSION(mutex_ptr)
100
101 /* If trace is enabled, unregister this object. */
102 TX_TRACE_OBJECT_UNREGISTER(mutex_ptr)
103
104 /* Log this kernel call. */
105 TX_EL_MUTEX_DELETE_INSERT
106
107 /* Clear the mutex ID to make it invalid. */
108 mutex_ptr -> tx_mutex_id = TX_CLEAR_ID;
109
110 /* Decrement the created count. */
111 _tx_mutex_created_count--;
112
113 /* See if the mutex is the only one on the list. */
114 if (_tx_mutex_created_count == TX_EMPTY)
115 {
116
117 /* Only created mutex, just set the created list to NULL. */
118 _tx_mutex_created_ptr = TX_NULL;
119 }
120 else
121 {
122
123 /* Link-up the neighbors. */
124 next_mutex = mutex_ptr -> tx_mutex_created_next;
125 previous_mutex = mutex_ptr -> tx_mutex_created_previous;
126 next_mutex -> tx_mutex_created_previous = previous_mutex;
127 previous_mutex -> tx_mutex_created_next = next_mutex;
128
129 /* See if we have to update the created list head pointer. */
130 if (_tx_mutex_created_ptr == mutex_ptr)
131 {
132
133 /* Yes, move the head pointer to the next link. */
134 _tx_mutex_created_ptr = next_mutex;
135 }
136 }
137
138 /* Temporarily disable preemption. */
139 _tx_thread_preempt_disable++;
140
141 /* Pickup the suspension information. */
142 thread_ptr = mutex_ptr -> tx_mutex_suspension_list;
143 mutex_ptr -> tx_mutex_suspension_list = TX_NULL;
144 suspended_count = mutex_ptr -> tx_mutex_suspended_count;
145 mutex_ptr -> tx_mutex_suspended_count = TX_NO_SUSPENSIONS;
146
147
148 /* Determine if the mutex is currently on a thread's ownership list. */
149
150 /* Setup pointer to owner of mutex. */
151 owner_thread = mutex_ptr -> tx_mutex_owner;
152
153 /* Determine if there is a valid thread pointer. */
154 if (owner_thread != TX_NULL)
155 {
156
157 /* Yes, remove this mutex from the owned list. */
158
159 /* Set the ownership count to 1. */
160 mutex_ptr -> tx_mutex_ownership_count = ((UINT) 1);
161
162 /* Restore interrupts. */
163 TX_RESTORE
164
165 #ifdef TX_MISRA_ENABLE
166 /* Release the mutex. */
167 do
168 {
169 status = _tx_mutex_put(mutex_ptr);
170 } while (status != TX_SUCCESS);
171 #else
172 _tx_mutex_put(mutex_ptr);
173 #endif
174
175 /* Disable interrupts. */
176 TX_DISABLE
177 }
178
179 /* Restore interrupts. */
180 TX_RESTORE
181
182 /* Walk through the mutex list to resume any and all threads suspended
183 on this mutex. */
184 while (suspended_count != ((ULONG) 0))
185 {
186
187 /* Decrement the suspension count. */
188 suspended_count--;
189
190 /* Lockout interrupts. */
191 TX_DISABLE
192
193 /* Clear the cleanup pointer, this prevents the timeout from doing
194 anything. */
195 thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
196
197 /* Set the return status in the thread to TX_DELETED. */
198 thread_ptr -> tx_thread_suspend_status = TX_DELETED;
199
200 /* Move the thread pointer ahead. */
201 next_thread = thread_ptr -> tx_thread_suspended_next;
202
203 #ifdef TX_NOT_INTERRUPTABLE
204
205 /* Resume the thread! */
206 _tx_thread_system_ni_resume(thread_ptr);
207
208 /* Restore interrupts. */
209 TX_RESTORE
210 #else
211
212 /* Temporarily disable preemption again. */
213 _tx_thread_preempt_disable++;
214
215 /* Restore interrupts. */
216 TX_RESTORE
217
218 /* Resume the thread. */
219 _tx_thread_system_resume(thread_ptr);
220 #endif
221
222 /* Move to next thread. */
223 thread_ptr = next_thread;
224 }
225
226 /* Execute Port-Specific completion processing. If needed, it is typically defined in tx_port.h. */
227 TX_MUTEX_DELETE_PORT_COMPLETION(mutex_ptr)
228
229 /* Disable interrupts. */
230 TX_DISABLE
231
232 /* Release previous preempt disable. */
233 _tx_thread_preempt_disable--;
234
235 /* Restore interrupts. */
236 TX_RESTORE
237
238 /* Check for preemption. */
239 _tx_thread_system_preempt_check();
240
241 /* Return TX_SUCCESS. */
242 return(TX_SUCCESS);
243 }
244
245