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 /** NetX Component */
16 /** */
17 /** Transmission Control Protocol (TCP) */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define NX_SOURCE_CODE
23
24
25 /* Include necessary system files. */
26
27 #include "nx_api.h"
28 #include "tx_thread.h"
29 #include "tx_timer.h"
30 #include "nx_ip.h"
31 #include "nx_tcp.h"
32
33
34 /**************************************************************************/
35 /* */
36 /* FUNCTION RELEASE */
37 /* */
38 /* _nx_tcp_client_bind_cleanup PORTABLE C */
39 /* 6.1 */
40 /* AUTHOR */
41 /* */
42 /* Yuxin Zhou, Microsoft Corporation */
43 /* */
44 /* DESCRIPTION */
45 /* */
46 /* This function processes TCP bind timeout and thread terminate */
47 /* actions that require the TCP socket data structures to be cleaned */
48 /* up. */
49 /* */
50 /* INPUT */
51 /* */
52 /* thread_ptr Pointer to suspended thread's */
53 /* control block */
54 /* */
55 /* OUTPUT */
56 /* */
57 /* None */
58 /* */
59 /* CALLS */
60 /* */
61 /* tx_event_flags_set Set event flag */
62 /* _tx_thread_system_resume Resume thread service */
63 /* */
64 /* CALLED BY */
65 /* */
66 /* _nx_tcp_deferred_cleanup_check Deferred cleanup processing */
67 /* _nx_tcp_client_socket_unbind Socket unbind processing */
68 /* _tx_thread_timeout Thread timeout processing */
69 /* _tx_thread_terminate Thread terminate processing */
70 /* */
71 /* RELEASE HISTORY */
72 /* */
73 /* DATE NAME DESCRIPTION */
74 /* */
75 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
76 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
77 /* resulting in version 6.1 */
78 /* */
79 /**************************************************************************/
_nx_tcp_client_bind_cleanup(TX_THREAD * thread_ptr NX_CLEANUP_PARAMETER)80 VOID _nx_tcp_client_bind_cleanup(TX_THREAD *thread_ptr NX_CLEANUP_PARAMETER)
81 {
82
83 TX_INTERRUPT_SAVE_AREA
84
85 NX_IP *ip_ptr;
86 NX_TCP_SOCKET *socket_ptr; /* Working socket pointer */
87 NX_TCP_SOCKET *owning_socket_ptr; /* Socket owning the port */
88
89 NX_CLEANUP_EXTENSION
90
91 /* Disable interrupts to remove the suspended thread from the TCP socket. */
92 TX_DISABLE
93
94 /* Setup pointer to TCP socket control block. */
95 socket_ptr = (NX_TCP_SOCKET *)thread_ptr -> tx_thread_suspend_control_block;
96
97 /* Determine if the socket pointer is valid. */
98 if ((!socket_ptr) || (socket_ptr -> nx_tcp_socket_id != NX_TCP_ID))
99 {
100
101 /* Restore interrupts. */
102 TX_RESTORE
103
104 return;
105 }
106
107 /* Determine if the cleanup is still required. */
108 if (!(thread_ptr -> tx_thread_suspend_cleanup))
109 {
110
111 /* Restore interrupts. */
112 TX_RESTORE
113
114 return;
115 }
116
117 /* Determine if the caller is an ISR or the system timer thread. */
118 #ifndef TX_TIMER_PROCESS_IN_ISR
119 if ((TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))
120 #else
121 if (TX_THREAD_GET_SYSTEM_STATE())
122 #endif
123 {
124
125 /* Yes, defer the processing to the NetX IP thread. */
126
127 /* Yes, change the suspend cleanup routine to indicate the cleanup is deferred. */
128 thread_ptr -> tx_thread_suspend_cleanup = _nx_tcp_cleanup_deferred;
129
130 /* Pickup the IP pointer. */
131 ip_ptr = socket_ptr -> nx_tcp_socket_ip_ptr;
132
133 /* Restore interrupts. */
134 TX_RESTORE
135
136 /* Set the deferred cleanup flag for the IP thread. */
137 tx_event_flags_set(&(ip_ptr -> nx_ip_events), NX_IP_TCP_CLEANUP_DEFERRED, TX_OR);
138
139 /* Return to caller. */
140 return;
141 }
142 else
143 {
144
145 /* Yes, we still have thread suspension! */
146
147 /* Clear the socket bind in progress flag. */
148 socket_ptr -> nx_tcp_socket_bind_in_progress = NX_NULL;
149
150 /* Clear the suspension cleanup flag. */
151 thread_ptr -> tx_thread_suspend_cleanup = TX_NULL;
152
153 /* Pickup the socket owning the port. This pointer was
154 saved in the bind processing prior to suspension. */
155 owning_socket_ptr = socket_ptr -> nx_tcp_socket_bound_previous;
156
157 /* Remove the suspended thread from the list. */
158
159 /* See if this is the only suspended thread on the list. */
160 if (thread_ptr == thread_ptr -> tx_thread_suspended_next)
161 {
162
163 /* Yes, the only suspended thread. */
164
165 /* Update the head pointer. */
166 owning_socket_ptr -> nx_tcp_socket_bind_suspension_list = NX_NULL;
167 }
168 else
169 {
170
171 /* At least one more thread is on the same suspension list. */
172
173 /* Update the list head pointer. */
174 owning_socket_ptr -> nx_tcp_socket_bind_suspension_list = thread_ptr -> tx_thread_suspended_next;
175
176 /* Update the links of the adjacent threads. */
177 (thread_ptr -> tx_thread_suspended_next) -> tx_thread_suspended_previous =
178 thread_ptr -> tx_thread_suspended_previous;
179 (thread_ptr -> tx_thread_suspended_previous) -> tx_thread_suspended_next =
180 thread_ptr -> tx_thread_suspended_next;
181 }
182
183 /* Decrement the suspension count. */
184 owning_socket_ptr -> nx_tcp_socket_bind_suspended_count--;
185
186 /* Now we need to determine if this cleanup is from a terminate, timeout,
187 or from a wait abort. */
188 if (thread_ptr -> tx_thread_state == TX_TCP_IP)
189 {
190
191 /* Thread still suspended on the TCP socket. Setup return error status and
192 resume the thread. */
193
194 /* Setup return status. */
195 thread_ptr -> tx_thread_suspend_status = NX_PORT_UNAVAILABLE;
196
197 /* Temporarily disable preemption. */
198 _tx_thread_preempt_disable++;
199
200 /* Restore interrupts. */
201 TX_RESTORE
202
203 /* Resume the thread! Check for preemption even though we are executing
204 from the system timer thread right now which normally executes at the
205 highest priority. */
206 _tx_thread_system_resume(thread_ptr);
207
208 /* Finished, just return. */
209 return;
210 }
211 }
212
213 /* Restore interrupts. */
214 TX_RESTORE
215 }
216
217