Skip to content

Commit b54f9ce

Browse files
pasisgalnoam
authored andcommitted
issue: 3788369 Optimize is_rts() checks in data path
While a socket is locked, it's state cannot be changed and the only scenario to change the state is to call polling or TCP timers. In the TX path we don't call timers and polling is called when the send buffer is full. Therefore, it's enough to check the connection state under the lock once for non-blocking sockets. For blocking sockets the check can be moved after the polling, because the connection state cannot be changed before. Check for g_b_exit is relevant only for blocking operations, so check it just before polling. Signed-off-by: Dmytro Podgornyi <[email protected]>
1 parent 12b0365 commit b54f9ce

File tree

1 file changed

+32
-39
lines changed

1 file changed

+32
-39
lines changed

src/core/sock/sockinfo_tcp.cpp

Lines changed: 32 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,9 +1052,6 @@ ssize_t sockinfo_tcp::tcp_tx(xlio_tx_call_attr_t &tx_arg)
10521052
return ret;
10531053
}
10541054

1055-
if (unlikely(!is_connected_and_ready_to_send())) {
1056-
return -1;
1057-
}
10581055
si_tcp_logfunc("tx: iov=%p niovs=%d", p_iov, sz_iov);
10591056

10601057
if (m_sysvar_rx_poll_on_tx_tcp) {
@@ -1079,6 +1076,9 @@ ssize_t sockinfo_tcp::tcp_tx(xlio_tx_call_attr_t &tx_arg)
10791076
[](size_t sum, const iovec &curr) { return sum + curr.iov_len; });
10801077
lock_tcp_con();
10811078

1079+
if (unlikely(!is_connected_and_ready_to_send())) {
1080+
return tcp_tx_handle_errno_and_unlock(errno);
1081+
}
10821082
if (TCP_WND_UNAVALABLE(m_pcb, total_iov_len)) {
10831083
return tcp_tx_handle_errno_and_unlock(EAGAIN);
10841084
}
@@ -1099,13 +1099,8 @@ ssize_t sockinfo_tcp::tcp_tx(xlio_tx_call_attr_t &tx_arg)
10991099
unsigned tx_size = sndbuf_available();
11001100

11011101
if (tx_size == 0) {
1102-
if (unlikely(!is_rts())) {
1103-
si_tcp_logdbg("TX on disconnected socket");
1104-
return tcp_tx_handle_errno_and_unlock(ECONNRESET);
1105-
}
11061102
// force out TCP data before going on wait()
11071103
tcp_output(&m_pcb);
1108-
11091104
return tcp_tx_handle_sndbuf_unavailable(total_tx, is_dummy, is_non_file_zerocopy,
11101105
errno_tmp);
11111106
}
@@ -1134,15 +1129,6 @@ ssize_t sockinfo_tcp::tcp_tx(xlio_tx_call_attr_t &tx_arg)
11341129
tx_size = std::min(remainder, tx_size);
11351130
}
11361131

1137-
if (unlikely(!is_rts())) {
1138-
si_tcp_logdbg("TX on disconnected socket");
1139-
return tcp_tx_handle_errno_and_unlock(ECONNRESET);
1140-
}
1141-
if (unlikely(g_b_exit)) {
1142-
return tcp_tx_handle_partial_send_and_unlock(total_tx, EINTR, is_dummy,
1143-
is_non_file_zerocopy, errno_tmp);
1144-
}
1145-
11461132
const struct iovec iov = {.iov_base = tx_ptr, .iov_len = tx_size};
11471133
err = tcp_write_express(&m_pcb, &iov, 1, &tx_arg.priv);
11481134
if (unlikely(err != ERR_OK)) {
@@ -1211,6 +1197,9 @@ ssize_t sockinfo_tcp::tcp_tx_slow_path(xlio_tx_call_attr_t &tx_arg)
12111197

12121198
lock_tcp_con();
12131199

1200+
if (unlikely(!is_connected_and_ready_to_send())) {
1201+
return tcp_tx_handle_errno_and_unlock(errno);
1202+
}
12141203
if (cannot_do_requested_dummy_send(m_pcb, tx_arg)) {
12151204
return tcp_tx_handle_errno_and_unlock(EAGAIN);
12161205
}
@@ -1246,10 +1235,6 @@ ssize_t sockinfo_tcp::tcp_tx_slow_path(xlio_tx_call_attr_t &tx_arg)
12461235
* - block until space is available
12471236
*/
12481237
if (tx_size == 0) {
1249-
if (unlikely(!is_rts())) {
1250-
si_tcp_logdbg("TX on disconnected socket");
1251-
return tcp_tx_handle_errno_and_unlock(ECONNRESET);
1252-
}
12531238
// force out TCP data before going on wait()
12541239
tcp_output(&m_pcb);
12551240

@@ -1259,7 +1244,16 @@ ssize_t sockinfo_tcp::tcp_tx_slow_path(xlio_tx_call_attr_t &tx_arg)
12591244
errno_tmp);
12601245
}
12611246

1247+
if (unlikely(g_b_exit)) {
1248+
return tcp_tx_handle_partial_send_and_unlock(total_tx, EINTR, is_dummy,
1249+
is_send_zerocopy, errno_tmp);
1250+
}
1251+
12621252
tx_size = tx_wait(block_this_run);
1253+
if (unlikely(!is_rts())) {
1254+
si_tcp_logdbg("TX on disconnected socket");
1255+
return tcp_tx_handle_errno_and_unlock(ECONNRESET);
1256+
}
12631257
}
12641258

12651259
tx_size = std::min<size_t>(p_iov[i].iov_len - pos, tx_size);
@@ -1276,15 +1270,6 @@ ssize_t sockinfo_tcp::tcp_tx_slow_path(xlio_tx_call_attr_t &tx_arg)
12761270
tx_size = std::min(remainder, tx_size);
12771271
}
12781272
do {
1279-
if (unlikely(!is_rts())) {
1280-
si_tcp_logdbg("TX on disconnected socket");
1281-
return tcp_tx_handle_errno_and_unlock(ECONNRESET);
1282-
}
1283-
if (unlikely(g_b_exit)) {
1284-
return tcp_tx_handle_partial_send_and_unlock(total_tx, EINTR, is_dummy,
1285-
is_send_zerocopy, errno_tmp);
1286-
}
1287-
12881273
err_t err;
12891274
if (apiflags & XLIO_TX_PACKET_ZEROCOPY) {
12901275
const struct iovec iov = {.iov_base = tx_ptr, .iov_len = tx_size};
@@ -1315,7 +1300,16 @@ ssize_t sockinfo_tcp::tcp_tx_slow_path(xlio_tx_call_attr_t &tx_arg)
13151300
}
13161301
}
13171302

1303+
if (unlikely(g_b_exit)) {
1304+
return tcp_tx_handle_partial_send_and_unlock(total_tx, EINTR, is_dummy,
1305+
is_send_zerocopy, errno_tmp);
1306+
}
1307+
13181308
rx_wait(poll_count, true);
1309+
if (unlikely(!is_rts())) {
1310+
si_tcp_logdbg("TX on disconnected socket");
1311+
return tcp_tx_handle_errno_and_unlock(ECONNRESET);
1312+
}
13191313

13201314
// AlexV:Avoid from going to sleep, for the blocked socket of course, since
13211315
// progress engine may consume an arrived credit and it will not wakeup the
@@ -6168,10 +6162,6 @@ inline bool sockinfo_tcp::handle_bind_no_port(int &bind_ret, in_port_t in_port,
61686162
int sockinfo_tcp::tcp_tx_express(const struct iovec *iov, unsigned iov_len, uint32_t mkey,
61696163
unsigned flags, void *opaque_op)
61706164
{
6171-
if (unlikely(!is_connected_and_ready_to_send())) {
6172-
return -1;
6173-
}
6174-
61756165
pbuf_desc mdesc;
61766166

61776167
switch (flags & XLIO_EXPRESS_OP_TYPE_MASK) {
@@ -6194,6 +6184,10 @@ int sockinfo_tcp::tcp_tx_express(const struct iovec *iov, unsigned iov_len, uint
61946184

61956185
lock_tcp_con();
61966186

6187+
if (unlikely(!is_connected_and_ready_to_send())) {
6188+
return tcp_tx_handle_errno_and_unlock(errno);
6189+
}
6190+
61976191
err_t err = tcp_write_express(&m_pcb, iov, iov_len, &mdesc);
61986192
if (unlikely(err != ERR_OK)) {
61996193
// The only error in tcp_write_express() is a memory error.
@@ -6216,10 +6210,6 @@ int sockinfo_tcp::tcp_tx_express(const struct iovec *iov, unsigned iov_len, uint
62166210

62176211
int sockinfo_tcp::tcp_tx_express_inline(const struct iovec *iov, unsigned iov_len, unsigned flags)
62186212
{
6219-
if (unlikely(!is_connected_and_ready_to_send())) {
6220-
return -1;
6221-
}
6222-
62236213
pbuf_desc mdesc;
62246214
int bytes_written = 0;
62256215

@@ -6228,6 +6218,10 @@ int sockinfo_tcp::tcp_tx_express_inline(const struct iovec *iov, unsigned iov_le
62286218

62296219
lock_tcp_con();
62306220

6221+
if (unlikely(!is_connected_and_ready_to_send())) {
6222+
return tcp_tx_handle_errno_and_unlock(errno);
6223+
}
6224+
62316225
for (unsigned i = 0; i < iov_len; ++i) {
62326226
bytes_written += iov[i].iov_len;
62336227
err_t err = tcp_write(&m_pcb, iov[i].iov_base, iov[i].iov_len, 0, &mdesc);
@@ -6323,7 +6317,6 @@ ssize_t sockinfo_tcp::tcp_tx_handle_partial_send_and_unlock(ssize_t total_tx, in
63236317

63246318
bool sockinfo_tcp::is_connected_and_ready_to_send()
63256319
{
6326-
/* TODO should we add !g_b_exit here? */
63276320
if (unlikely(!is_rts())) {
63286321
if (m_conn_state == TCP_CONN_TIMEOUT) {
63296322
si_tcp_logdbg("TX timed out");

0 commit comments

Comments
 (0)