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