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 /** NetX Component */
17 /** */
18 /** Packet Pool Management (Packet) */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23 #define NX_SOURCE_CODE
24
25
26 /* Include necessary system files. */
27
28 #include "nx_api.h"
29 #include "tx_thread.h"
30 #include "nx_packet.h"
31
32
33 /**************************************************************************/
34 /* */
35 /* FUNCTION RELEASE */
36 /* */
37 /* _nx_packet_release PORTABLE C */
38 /* 6.1 */
39 /* AUTHOR */
40 /* */
41 /* Yuxin Zhou, Microsoft Corporation */
42 /* */
43 /* DESCRIPTION */
44 /* */
45 /* This function releases the packet chain back to the appropriate */
46 /* packet pools. */
47 /* */
48 /* INPUT */
49 /* */
50 /* packet_ptr Pointer of packet to release */
51 /* */
52 /* OUTPUT */
53 /* */
54 /* status Completion status */
55 /* */
56 /* CALLS */
57 /* */
58 /* _tx_thread_system_resume Resume suspended thread */
59 /* */
60 /* CALLED BY */
61 /* */
62 /* Application Code */
63 /* */
64 /* RELEASE HISTORY */
65 /* */
66 /* DATE NAME DESCRIPTION */
67 /* */
68 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
69 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
70 /* resulting in version 6.1 */
71 /* */
72 /**************************************************************************/
_nx_packet_release(NX_PACKET * packet_ptr)73 UINT _nx_packet_release(NX_PACKET *packet_ptr)
74 {
75
76 TX_INTERRUPT_SAVE_AREA
77
78 NX_PACKET_POOL *pool_ptr; /* Pool pointer */
79 TX_THREAD *thread_ptr; /* Working thread pointer */
80 #ifndef NX_DISABLE_PACKET_CHAIN
81 NX_PACKET *next_packet; /* Working block pointer */
82 #endif /* NX_DISABLE_PACKET_CHAIN */
83
84
85 /* If trace is enabled, insert this event into the trace buffer. */
86 NX_TRACE_IN_LINE_INSERT(NX_TRACE_PACKET_RELEASE, packet_ptr, packet_ptr -> nx_packet_union_next.nx_packet_tcp_queue_next, (packet_ptr -> nx_packet_pool_owner) -> nx_packet_pool_available, 0, NX_TRACE_PACKET_EVENTS, 0, 0);
87
88 #ifndef NX_DISABLE_PACKET_CHAIN
89 /* Loop to free all packets chained together, not assuming they are
90 from the same pool. */
91 while (packet_ptr)
92 {
93 #endif /* NX_DISABLE_PACKET_CHAIN */
94
95 /* Check to see if the packet is releasable. */
96 /*lint -e{923} suppress cast of ULONG to pointer. */
97 if (packet_ptr -> nx_packet_union_next.nx_packet_tcp_queue_next != ((NX_PACKET *)NX_PACKET_ALLOCATED))
98 {
99
100 #ifndef NX_DISABLE_PACKET_INFO
101 /* Pickup the pool pointer. */
102 pool_ptr = packet_ptr -> nx_packet_pool_owner;
103
104 /* Check for a good pool pointer... error must be the packet! */
105 if ((pool_ptr) && (pool_ptr -> nx_packet_pool_id == NX_PACKET_POOL_ID))
106 {
107
108 /* Increment the packet pool invalid release error count. */
109 pool_ptr -> nx_packet_pool_invalid_releases++;
110 }
111 #endif
112
113 /* Return an error indicating the packet could not be released. */
114 return(NX_PTR_ERROR);
115 }
116 /* End of packet check. */
117
118 #ifndef NX_DISABLE_PACKET_CHAIN
119 /* Pickup the next packet. */
120 next_packet = packet_ptr -> nx_packet_next;
121 #endif /* NX_DISABLE_PACKET_CHAIN */
122
123 /* Add debug information. */
124 NX_PACKET_DEBUG(__FILE__, __LINE__, packet_ptr);
125
126 /* Disable interrupts to put this packet back in the packet pool. */
127 TX_DISABLE
128
129 /* Pickup the pool pointer. */
130 pool_ptr = packet_ptr -> nx_packet_pool_owner;
131
132 /* Determine if there are any threads suspended on the block pool. */
133 thread_ptr = pool_ptr -> nx_packet_pool_suspension_list;
134 if (thread_ptr)
135 {
136
137 /* Remove the suspended thread from the list. */
138
139 /* See if this is the only suspended thread on the list. */
140 if (thread_ptr == thread_ptr -> tx_thread_suspended_next)
141 {
142
143 /* Yes, the only suspended thread. */
144
145 /* Update the head pointer. */
146 pool_ptr -> nx_packet_pool_suspension_list = NX_NULL;
147 }
148 else
149 {
150
151 /* At least one more thread is on the same expiration list. */
152
153 /* Update the list head pointer. */
154 pool_ptr -> nx_packet_pool_suspension_list = thread_ptr -> tx_thread_suspended_next;
155
156 /* Update the links of the adjacent threads. */
157 (thread_ptr -> tx_thread_suspended_next) -> tx_thread_suspended_previous =
158 thread_ptr -> tx_thread_suspended_previous;
159 (thread_ptr -> tx_thread_suspended_previous) -> tx_thread_suspended_next =
160 thread_ptr -> tx_thread_suspended_next;
161 }
162
163 /* Decrement the suspension count. */
164 pool_ptr -> nx_packet_pool_suspended_count--;
165
166 /* Prepare for resumption of the first thread. */
167
168 /* Clear cleanup routine to avoid timeout. */
169 thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
170
171 /* Temporarily disable preemption. */
172 _tx_thread_preempt_disable++;
173
174 /* Restore interrupts. */
175 TX_RESTORE
176
177 /* Adjust this packet to look just like a new packet. */
178 packet_ptr -> nx_packet_queue_next = NX_NULL;
179 #ifndef NX_DISABLE_PACKET_CHAIN
180 packet_ptr -> nx_packet_next = NX_NULL;
181 packet_ptr -> nx_packet_last = NX_NULL;
182 #endif /* NX_DISABLE_PACKET_CHAIN */
183 packet_ptr -> nx_packet_length = 0;
184 packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_data_start + (thread_ptr -> tx_thread_suspend_info);
185 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr;
186 packet_ptr -> nx_packet_address.nx_packet_interface_ptr = NX_NULL;
187 #ifdef NX_ENABLE_INTERFACE_CAPABILITY
188 packet_ptr -> nx_packet_interface_capability_flag = 0;
189 #endif /* NX_ENABLE_INTERFACE_CAPABILITY */
190 /* Set the TCP queue to the value that indicates it has been allocated. */
191 /*lint -e{923} suppress cast of ULONG to pointer. */
192 packet_ptr -> nx_packet_union_next.nx_packet_tcp_queue_next = (NX_PACKET *)NX_PACKET_ALLOCATED;
193
194 #ifdef FEATURE_NX_IPV6
195
196 /* Clear the option state. */
197 packet_ptr -> nx_packet_option_state = 0;
198 #endif /* FEATURE_NX_IPV6 */
199
200 #ifdef NX_IPSEC_ENABLE
201
202 /* Clear the ipsec state. */
203 packet_ptr -> nx_packet_ipsec_state = 0;
204 #endif /* NX_IPSEC_ENABLE */
205
206 /* Clear the IP version. */
207 packet_ptr -> nx_packet_ip_version = 0;
208
209 /* Clear the IP identification flag. */
210 packet_ptr -> nx_packet_identical_copy = NX_FALSE;
211
212 /* Initialize the IP header length. */
213 packet_ptr -> nx_packet_ip_header_length = 0;
214
215 /* Return this block pointer to the suspended thread waiting for
216 a block. */
217 *((NX_PACKET **)thread_ptr -> tx_thread_additional_suspend_info) = packet_ptr;
218
219 /* Put return status into the thread control block. */
220 thread_ptr -> tx_thread_suspend_status = NX_SUCCESS;
221
222 /* Resume thread. */
223 _tx_thread_system_resume(thread_ptr);
224 }
225 else
226 {
227
228 /* No thread is suspended for a memory block. */
229
230 /* Mark the packet as free. */
231 /*lint -e{923} suppress cast of ULONG to pointer. */
232 packet_ptr -> nx_packet_union_next.nx_packet_tcp_queue_next = (NX_PACKET *)NX_PACKET_FREE;
233
234 /* Put the packet back in the available list. */
235 packet_ptr -> nx_packet_queue_next = pool_ptr -> nx_packet_pool_available_list;
236
237 /* Adjust the head pointer. */
238 pool_ptr -> nx_packet_pool_available_list = packet_ptr;
239
240 /* Increment the count of available blocks. */
241 pool_ptr -> nx_packet_pool_available++;
242
243 /* Restore interrupts. */
244 TX_RESTORE
245 }
246
247 #ifndef NX_DISABLE_PACKET_CHAIN
248 /* Move to the next packet in the list. */
249 packet_ptr = next_packet;
250 }
251 #endif /* NX_DISABLE_PACKET_CHAIN */
252
253 /* Return completion status. */
254 return(NX_SUCCESS);
255 }
256
257