Skip to content

Commit 86105fb

Browse files
rluboscarlescufi
authored andcommitted
net: sockets: Monitor TCP transmit state with semaphore
Utilize the TCP semaphore monitoring transmit status at the socket layer. This allows to resume transfer as soon as possible instead of waiting blindly. Signed-off-by: Robert Lubos <[email protected]>
1 parent d35d9a6 commit 86105fb

File tree

1 file changed

+72
-49
lines changed

1 file changed

+72
-49
lines changed

subsys/net/lib/sockets/sockets.c

Lines changed: 72 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ LOG_MODULE_REGISTER(net_sock, CONFIG_NET_SOCKETS_LOG_LEVEL);
2828
#include "../../ip/net_stats.h"
2929

3030
#include "sockets_internal.h"
31+
#include "../../ip/tcp_internal.h"
3132

3233
#define SET_ERRNO(x) \
3334
{ int _err = x; if (_err < 0) { errno = -_err; return -1; } }
@@ -653,6 +654,65 @@ static inline int z_vrfy_zsock_accept(int sock, struct sockaddr *addr,
653654
#define WAIT_BUFS K_MSEC(100)
654655
#define MAX_WAIT_BUFS K_SECONDS(10)
655656

657+
static int send_check_and_wait(struct net_context *ctx, int status,
658+
uint64_t buf_timeout, k_timeout_t timeout)
659+
{
660+
int64_t remaining;
661+
662+
if (!K_TIMEOUT_EQ(timeout, K_FOREVER)) {
663+
goto out;
664+
}
665+
666+
if (status != -ENOBUFS && status != -EAGAIN) {
667+
goto out;
668+
}
669+
670+
/* If we cannot get any buffers in reasonable
671+
* amount of time, then do not wait forever as
672+
* there might be some bigger issue.
673+
* If we get -EAGAIN and cannot recover, then
674+
* it means that the sending window is blocked
675+
* and we just cannot send anything.
676+
*/
677+
remaining = buf_timeout - sys_clock_tick_get();
678+
if (remaining <= 0) {
679+
if (status == -ENOBUFS) {
680+
status = -ENOMEM;
681+
} else {
682+
status = -ENOBUFS;
683+
}
684+
685+
goto out;
686+
}
687+
688+
if (status == -ENOBUFS) {
689+
/* We can monitor net_pkt/net_buf avaialbility, so just wait. */
690+
k_sleep(WAIT_BUFS);
691+
}
692+
693+
if (status == -EAGAIN) {
694+
if (IS_ENABLED(CONFIG_NET_NATIVE_TCP) &&
695+
net_context_get_type(ctx) == SOCK_STREAM) {
696+
struct k_poll_event event;
697+
698+
k_poll_event_init(&event,
699+
K_POLL_TYPE_SEM_AVAILABLE,
700+
K_POLL_MODE_NOTIFY_ONLY,
701+
net_tcp_tx_sem_get(ctx));
702+
703+
k_poll(&event, 1, WAIT_BUFS);
704+
} else {
705+
k_sleep(WAIT_BUFS);
706+
}
707+
}
708+
709+
return 0;
710+
711+
out:
712+
errno = -status;
713+
return -1;
714+
}
715+
656716
ssize_t zsock_sendto_ctx(struct net_context *ctx, const void *buf, size_t len,
657717
int flags,
658718
const struct sockaddr *dest_addr, socklen_t addrlen)
@@ -689,33 +749,13 @@ ssize_t zsock_sendto_ctx(struct net_context *ctx, const void *buf, size_t len,
689749
}
690750

691751
if (status < 0) {
692-
if (((status == -ENOBUFS) || (status == -EAGAIN)) &&
693-
K_TIMEOUT_EQ(timeout, K_FOREVER)) {
694-
/* If we cannot get any buffers in reasonable
695-
* amount of time, then do not wait forever as
696-
* there might be some bigger issue.
697-
* If we get -EAGAIN and cannot recover, then
698-
* it means that the sending window is blocked
699-
* and we just cannot send anything.
700-
*/
701-
int64_t remaining = buf_timeout - sys_clock_tick_get();
702-
703-
if (remaining <= 0) {
704-
if (status == -ENOBUFS) {
705-
errno = ENOMEM;
706-
} else {
707-
errno = ENOBUFS;
708-
}
709-
710-
return -1;
711-
}
712-
713-
k_sleep(WAIT_BUFS);
714-
continue;
715-
} else {
716-
errno = -status;
717-
return -1;
752+
status = send_check_and_wait(ctx, status, buf_timeout,
753+
timeout);
754+
if (status < 0) {
755+
return status;
718756
}
757+
758+
continue;
719759
}
720760

721761
break;
@@ -767,32 +807,15 @@ ssize_t zsock_sendmsg_ctx(struct net_context *ctx, const struct msghdr *msg,
767807
while (1) {
768808
status = net_context_sendmsg(ctx, msg, flags, NULL, timeout, NULL);
769809
if (status < 0) {
770-
if (((status == -ENOBUFS) || (status == -EAGAIN)) &&
771-
K_TIMEOUT_EQ(timeout, K_FOREVER)) {
772-
/* If we cannot get any buffers in reasonable
773-
* amount of time, then do not wait forever as
774-
* there might be some bigger issue.
775-
* If we get -EAGAIN and cannot recover, then
776-
* it means that the sending window is blocked
777-
* and we just cannot send anything.
778-
*/
779-
int64_t remaining = buf_timeout - sys_clock_tick_get();
780-
781-
if (remaining <= 0) {
782-
if (status == -ENOBUFS) {
783-
errno = ENOMEM;
784-
} else {
785-
errno = ENOBUFS;
786-
}
787-
788-
return -1;
810+
if (status < 0) {
811+
status = send_check_and_wait(ctx, status,
812+
buf_timeout,
813+
timeout);
814+
if (status < 0) {
815+
return status;
789816
}
790817

791-
k_sleep(WAIT_BUFS);
792818
continue;
793-
} else {
794-
errno = -status;
795-
return -1;
796819
}
797820
}
798821

0 commit comments

Comments
 (0)