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 /** Block Pool */
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_block_pool.h"
31
32
33 /**************************************************************************/
34 /* */
35 /* FUNCTION RELEASE */
36 /* */
37 /* _tx_block_pool_prioritize PORTABLE C */
38 /* 6.1 */
39 /* AUTHOR */
40 /* */
41 /* William E. Lamie, Microsoft Corporation */
42 /* */
43 /* DESCRIPTION */
44 /* */
45 /* This function places the highest priority suspended thread at the */
46 /* front of the suspension list. All other threads remain in the same */
47 /* FIFO suspension order. */
48 /* */
49 /* INPUT */
50 /* */
51 /* pool_ptr Pointer to pool control block */
52 /* */
53 /* OUTPUT */
54 /* */
55 /* status Completion status */
56 /* */
57 /* CALLS */
58 /* */
59 /* _tx_thread_system_preempt_check Check for preemption */
60 /* */
61 /* CALLED BY */
62 /* */
63 /* Application Code */
64 /* */
65 /* RELEASE HISTORY */
66 /* */
67 /* DATE NAME DESCRIPTION */
68 /* */
69 /* 05-19-2020 William E. Lamie Initial Version 6.0 */
70 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
71 /* resulting in version 6.1 */
72 /* */
73 /**************************************************************************/
_tx_block_pool_prioritize(TX_BLOCK_POOL * pool_ptr)74 UINT _tx_block_pool_prioritize(TX_BLOCK_POOL *pool_ptr)
75 {
76
77 TX_INTERRUPT_SAVE_AREA
78
79 TX_THREAD *thread_ptr;
80 TX_THREAD *priority_thread_ptr;
81 TX_THREAD *head_ptr;
82 UINT suspended_count;
83 TX_THREAD *next_thread;
84 TX_THREAD *previous_thread;
85 UINT list_changed;
86
87
88 /* Disable interrupts. */
89 TX_DISABLE
90
91 /* If trace is enabled, insert this event into the trace buffer. */
92 TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_POOL_PRIORITIZE, pool_ptr, pool_ptr -> tx_block_pool_suspended_count, TX_POINTER_TO_ULONG_CONVERT(&suspended_count), 0, TX_TRACE_BLOCK_POOL_EVENTS)
93
94 /* Log this kernel call. */
95 TX_EL_BLOCK_POOL_PRIORITIZE_INSERT
96
97 /* Pickup the suspended count. */
98 suspended_count = pool_ptr -> tx_block_pool_suspended_count;
99
100 /* Determine if there are fewer than 2 suspended threads. */
101 if (suspended_count < ((UINT) 2))
102 {
103
104 /* Restore interrupts. */
105 TX_RESTORE
106 }
107
108 /* Determine if there how many threads are suspended on this block memory pool. */
109 else if (suspended_count == ((UINT) 2))
110 {
111
112 /* Pickup the head pointer and the next pointer. */
113 head_ptr = pool_ptr -> tx_block_pool_suspension_list;
114 next_thread = head_ptr -> tx_thread_suspended_next;
115
116 /* Determine if the next suspended thread has a higher priority. */
117 if ((next_thread -> tx_thread_priority) < (head_ptr -> tx_thread_priority))
118 {
119
120 /* Yes, move the list head to the next thread. */
121 pool_ptr -> tx_block_pool_suspension_list = next_thread;
122 }
123
124 /* Restore interrupts. */
125 TX_RESTORE
126 }
127 else
128 {
129
130 /* Remember the suspension count and head pointer. */
131 head_ptr = pool_ptr -> tx_block_pool_suspension_list;
132
133 /* Default the highest priority thread to the thread at the front of the list. */
134 priority_thread_ptr = head_ptr;
135
136 /* Setup search pointer. */
137 thread_ptr = priority_thread_ptr -> tx_thread_suspended_next;
138
139 /* Disable preemption. */
140 _tx_thread_preempt_disable++;
141
142 /* Set the list changed flag to false. */
143 list_changed = TX_FALSE;
144
145 /* Search through the list to find the highest priority thread. */
146 do
147 {
148
149 /* Is the current thread higher priority? */
150 if (thread_ptr -> tx_thread_priority < priority_thread_ptr -> tx_thread_priority)
151 {
152
153 /* Yes, remember that this thread is the highest priority. */
154 priority_thread_ptr = thread_ptr;
155 }
156
157 /* Restore interrupts temporarily. */
158 TX_RESTORE
159
160 /* Disable interrupts again. */
161 TX_DISABLE
162
163 /* Determine if any changes to the list have occurred while
164 interrupts were enabled. */
165
166 /* Is the list head the same? */
167 if (head_ptr != pool_ptr -> tx_block_pool_suspension_list)
168 {
169
170 /* The list head has changed, set the list changed flag. */
171 list_changed = TX_TRUE;
172 }
173 else
174 {
175
176 /* Is the suspended count the same? */
177 if (suspended_count != pool_ptr -> tx_block_pool_suspended_count)
178 {
179
180 /* The list head has changed, set the list changed flag. */
181 list_changed = TX_TRUE;
182 }
183 }
184
185 /* Determine if the list has changed. */
186 if (list_changed == TX_FALSE)
187 {
188
189 /* Move the thread pointer to the next thread. */
190 thread_ptr = thread_ptr -> tx_thread_suspended_next;
191 }
192 else
193 {
194
195 /* Remember the suspension count and head pointer. */
196 head_ptr = pool_ptr -> tx_block_pool_suspension_list;
197 suspended_count = pool_ptr -> tx_block_pool_suspended_count;
198
199 /* Default the highest priority thread to the thread at the front of the list. */
200 priority_thread_ptr = head_ptr;
201
202 /* Setup search pointer. */
203 thread_ptr = priority_thread_ptr -> tx_thread_suspended_next;
204
205 /* Reset the list changed flag. */
206 list_changed = TX_FALSE;
207 }
208
209 } while (thread_ptr != head_ptr);
210
211 /* Release preemption. */
212 _tx_thread_preempt_disable--;
213
214 /* Now determine if the highest priority thread is at the front
215 of the list. */
216 if (priority_thread_ptr != head_ptr)
217 {
218
219 /* No, we need to move the highest priority suspended thread to the
220 front of the list. */
221
222 /* First, remove the highest priority thread by updating the
223 adjacent suspended threads. */
224 next_thread = priority_thread_ptr -> tx_thread_suspended_next;
225 previous_thread = priority_thread_ptr -> tx_thread_suspended_previous;
226 next_thread -> tx_thread_suspended_previous = previous_thread;
227 previous_thread -> tx_thread_suspended_next = next_thread;
228
229 /* Now, link the highest priority thread at the front of the list. */
230 previous_thread = head_ptr -> tx_thread_suspended_previous;
231 priority_thread_ptr -> tx_thread_suspended_next = head_ptr;
232 priority_thread_ptr -> tx_thread_suspended_previous = previous_thread;
233 previous_thread -> tx_thread_suspended_next = priority_thread_ptr;
234 head_ptr -> tx_thread_suspended_previous = priority_thread_ptr;
235
236 /* Move the list head pointer to the highest priority suspended thread. */
237 pool_ptr -> tx_block_pool_suspension_list = priority_thread_ptr;
238 }
239
240 /* Restore interrupts. */
241 TX_RESTORE
242
243 /* Check for preemption. */
244 _tx_thread_system_preempt_check();
245 }
246
247 /* Return successful status. */
248 return(TX_SUCCESS);
249 }
250
251