drivers: nsos: release socket lock while polling
So far using recvfrom() and send() from two different threads was not possible, since thread attempting send() was blocked by the thread executing recvfrom(). All other APIs were also blocking each other, while it was not necessary. One example use case in Zephyr tree is MCUMGR SMP over UDP implementation, which resuled in communication timeouts. Release socket lock while actively polling, so other APIs executed from other threads can safely progress. Do this using k_condvar_wait() API with socket mutex, so that mutex is safely released and reaquired during wait. Signed-off-by: Marcin Niestroj <m.niestroj@emb.dev>
This commit is contained in:
committed by
Fabio Baltieri
parent
f6adcad1a6
commit
060682fb8d
@@ -46,6 +46,7 @@ struct nsos_socket;
|
||||
struct nsos_socket_poll {
|
||||
struct nsos_mid_pollfd mid;
|
||||
struct k_poll_signal signal;
|
||||
struct k_condvar *cond;
|
||||
|
||||
sys_dnode_t node;
|
||||
};
|
||||
@@ -287,6 +288,10 @@ static void pollcb(struct nsos_mid_pollfd *mid)
|
||||
struct nsos_socket_poll *poll = CONTAINER_OF(mid, struct nsos_socket_poll, mid);
|
||||
|
||||
k_poll_signal_raise(&poll->signal, poll->mid.revents);
|
||||
|
||||
if (poll->cond) {
|
||||
k_condvar_signal(poll->cond);
|
||||
}
|
||||
}
|
||||
|
||||
static int nsos_poll_prepare(struct nsos_socket *sock, struct zsock_pollfd *pfd,
|
||||
@@ -568,9 +573,22 @@ static int nsos_wait_for_poll(struct nsos_socket *sock, int events,
|
||||
struct k_poll_event poll_events[1];
|
||||
struct k_poll_event *pev = poll_events;
|
||||
struct k_poll_event *pev_end = poll_events + ARRAY_SIZE(poll_events);
|
||||
struct nsos_socket_poll socket_poll = {};
|
||||
struct k_mutex *lock = NULL;
|
||||
struct k_condvar cond;
|
||||
struct nsos_socket_poll socket_poll = {
|
||||
.cond = &cond,
|
||||
};
|
||||
bool lock_acquired;
|
||||
int ret;
|
||||
|
||||
lock_acquired = zvfs_get_obj_lock_and_cond(sock,
|
||||
&nsos_socket_fd_op_vtable.fd_vtable,
|
||||
&lock, NULL);
|
||||
__ASSERT(lock_acquired, "zvfs_get_obj_lock_and_cond() failed");
|
||||
__ASSERT_NO_MSG(lock != NULL);
|
||||
|
||||
k_condvar_init(&cond);
|
||||
|
||||
ret = nsos_adapt_dup(sock->poll.mid.fd);
|
||||
if (ret < 0) {
|
||||
goto return_ret;
|
||||
@@ -586,7 +604,7 @@ static int nsos_wait_for_poll(struct nsos_socket *sock, int events,
|
||||
goto close_dup;
|
||||
}
|
||||
|
||||
ret = k_poll(poll_events, ARRAY_SIZE(poll_events), timeout);
|
||||
ret = k_condvar_wait(&cond, lock, timeout);
|
||||
if (ret != 0 && ret != -EAGAIN && ret != -EINTR) {
|
||||
goto poll_update;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user