drivers: modem: modem_socket: Fix blocking modem_socket_poll

Before this commit, if a socket had received data before calling the
poll function, then the poll was waiting for either new data or a
timeout.
With this fix, polled socket are check for pending data before the
semaphore wait.

Signed-off-by: Xavier Chapron <xavier.chapron@stimio.fr>
This commit is contained in:
Xavier Chapron 2020-07-02 15:06:41 +02:00 committed by Anas Nashif
commit 7d67991a91

View file

@ -267,37 +267,61 @@ int modem_socket_poll(struct modem_socket_config *cfg,
return -EINVAL; return -EINVAL;
} }
k_sem_reset(&cfg->sem_poll);
for (i = 0; i < nfds; i++) { for (i = 0; i < nfds; i++) {
sock = modem_socket_from_fd(cfg, fds[i].fd); sock = modem_socket_from_fd(cfg, fds[i].fd);
if (sock) { if (sock) {
/* /*
* Handle user check for POLLOUT events: * Handle user check for POLLOUT events:
* we consider the socket to always be writeable. * we consider the socket to always be writable.
*/ */
if (fds[i].events & ZSOCK_POLLOUT) { if (fds[i].events & ZSOCK_POLLOUT) {
fds[i].revents |= ZSOCK_POLLOUT;
found_count++; found_count++;
break;
} else if (fds[i].events & ZSOCK_POLLIN) { } else if (fds[i].events & ZSOCK_POLLIN) {
sock->is_polled = true; sock->is_polled = true;
/*
* Handle check done after data reception on
* the socket. In this case that was received
* but as the socket wasn't polled, no sem_poll
* semaphore was given at that time. Therefore
* if there is a polled socket with data,
* increment found_count to escape the
* k_sem_take().
*/
if (sock->packet_sizes[0] > 0U) {
found_count++;
break;
}
} }
} }
} }
/* exit early if we've found rdy sockets */ /* Avoid waiting on semaphore if we have already found an event */
if (found_count) { ret = 0;
errno = 0; if (!found_count) {
return found_count; ret = k_sem_take(&cfg->sem_poll, K_MSEC(msecs));
} }
/* Reset counter as we reiterate on all polled sockets */
found_count = 0;
ret = k_sem_take(&cfg->sem_poll, K_MSEC(msecs));
for (i = 0; i < nfds; i++) { for (i = 0; i < nfds; i++) {
sock = modem_socket_from_fd(cfg, fds[i].fd); sock = modem_socket_from_fd(cfg, fds[i].fd);
if (!sock) { if (!sock) {
continue; continue;
} }
if ((fds[i].events & ZSOCK_POLLIN) && /*
(sock->packet_sizes[0] > 0U)) { * Handle user check for ZSOCK_POLLOUT events:
* we consider the socket to always be writable.
*/
if (fds[i].events & ZSOCK_POLLOUT) {
fds[i].revents |= ZSOCK_POLLOUT;
found_count++;
} else if ((fds[i].events & ZSOCK_POLLIN) &&
(sock->packet_sizes[0] > 0U)) {
fds[i].revents |= ZSOCK_POLLIN; fds[i].revents |= ZSOCK_POLLIN;
found_count++; found_count++;
} }