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_release PORTABLE C */
38 /* 6.1 */
39 /* AUTHOR */
40 /* */
41 /* William E. Lamie, Microsoft Corporation */
42 /* */
43 /* DESCRIPTION */
44 /* */
45 /* This function returns a previously allocated block to its */
46 /* associated memory block pool. */
47 /* */
48 /* INPUT */
49 /* */
50 /* block_ptr Pointer to memory block */
51 /* */
52 /* OUTPUT */
53 /* */
54 /* TX_SUCCESS Successful completion status */
55 /* */
56 /* CALLS */
57 /* */
58 /* _tx_thread_system_resume Resume thread service */
59 /* _tx_thread_system_ni_resume Non-interruptable resume thread */
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_release(VOID * block_ptr)74 UINT _tx_block_release(VOID *block_ptr)
75 {
76
77 TX_INTERRUPT_SAVE_AREA
78
79 TX_BLOCK_POOL *pool_ptr;
80 TX_THREAD *thread_ptr;
81 UCHAR *work_ptr;
82 UCHAR **return_block_ptr;
83 UCHAR **next_block_ptr;
84 UINT suspended_count;
85 TX_THREAD *next_thread;
86 TX_THREAD *previous_thread;
87
88
89 /* Disable interrupts to put this block back in the pool. */
90 TX_DISABLE
91
92 /* Pickup the pool pointer which is just previous to the starting
93 address of the block that the caller sees. */
94 work_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(block_ptr);
95 work_ptr = TX_UCHAR_POINTER_SUB(work_ptr, (sizeof(UCHAR *)));
96 next_block_ptr = TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(work_ptr);
97 pool_ptr = TX_UCHAR_TO_BLOCK_POOL_POINTER_CONVERT((*next_block_ptr));
98
99 #ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
100
101 /* Increment the total releases counter. */
102 _tx_block_pool_performance_release_count++;
103
104 /* Increment the number of releases on this pool. */
105 pool_ptr -> tx_block_pool_performance_release_count++;
106 #endif
107
108 /* If trace is enabled, insert this event into the trace buffer. */
109 TX_TRACE_IN_LINE_INSERT(TX_TRACE_BLOCK_RELEASE, pool_ptr, TX_POINTER_TO_ULONG_CONVERT(block_ptr), pool_ptr -> tx_block_pool_suspended_count, TX_POINTER_TO_ULONG_CONVERT(&work_ptr), TX_TRACE_BLOCK_POOL_EVENTS)
110
111 /* Log this kernel call. */
112 TX_EL_BLOCK_RELEASE_INSERT
113
114 /* Determine if there are any threads suspended on the block pool. */
115 thread_ptr = pool_ptr -> tx_block_pool_suspension_list;
116 if (thread_ptr != TX_NULL)
117 {
118
119 /* Remove the suspended thread from the list. */
120
121 /* Decrement the number of threads suspended. */
122 (pool_ptr -> tx_block_pool_suspended_count)--;
123
124 /* Pickup the suspended count. */
125 suspended_count = (pool_ptr -> tx_block_pool_suspended_count);
126
127 /* See if this is the only suspended thread on the list. */
128 if (suspended_count == TX_NO_SUSPENSIONS)
129 {
130
131 /* Yes, the only suspended thread. */
132
133 /* Update the head pointer. */
134 pool_ptr -> tx_block_pool_suspension_list = TX_NULL;
135 }
136 else
137 {
138
139 /* At least one more thread is on the same expiration list. */
140
141 /* Update the list head pointer. */
142 next_thread = thread_ptr -> tx_thread_suspended_next;
143 pool_ptr -> tx_block_pool_suspension_list = next_thread;
144
145 /* Update the links of the adjacent threads. */
146 previous_thread = thread_ptr -> tx_thread_suspended_previous;
147 next_thread -> tx_thread_suspended_previous = previous_thread;
148 previous_thread -> tx_thread_suspended_next = next_thread;
149 }
150
151 /* Prepare for resumption of the first thread. */
152
153 /* Clear cleanup routine to avoid timeout. */
154 thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
155
156 /* Return this block pointer to the suspended thread waiting for
157 a block. */
158 return_block_ptr = TX_VOID_TO_INDIRECT_UCHAR_POINTER_CONVERT(thread_ptr -> tx_thread_additional_suspend_info);
159 work_ptr = TX_VOID_TO_UCHAR_POINTER_CONVERT(block_ptr);
160 *return_block_ptr = work_ptr;
161
162 /* Put return status into the thread control block. */
163 thread_ptr -> tx_thread_suspend_status = TX_SUCCESS;
164
165 #ifdef TX_NOT_INTERRUPTABLE
166
167 /* Resume the thread! */
168 _tx_thread_system_ni_resume(thread_ptr);
169
170 /* Restore interrupts. */
171 TX_RESTORE
172 #else
173
174 /* Temporarily disable preemption. */
175 _tx_thread_preempt_disable++;
176
177 /* Restore interrupts. */
178 TX_RESTORE
179
180 /* Resume thread. */
181 _tx_thread_system_resume(thread_ptr);
182 #endif
183 }
184 else
185 {
186
187 /* No thread is suspended for a memory block. */
188
189 /* Put the block back in the available list. */
190 *next_block_ptr = pool_ptr -> tx_block_pool_available_list;
191
192 /* Adjust the head pointer. */
193 pool_ptr -> tx_block_pool_available_list = work_ptr;
194
195 /* Increment the count of available blocks. */
196 pool_ptr -> tx_block_pool_available++;
197
198 /* Restore interrupts. */
199 TX_RESTORE
200 }
201
202 /* Return successful completion status. */
203 return(TX_SUCCESS);
204 }
205
206