sock/posix: Make pending_recv shuffle more efficient

Instead of iterating the list, we can just manipulate the list
in a single step.

Signed-off-by: Ben Walker <benjamin.walker@intel.com>
Change-Id: I0172cdbce9af35a62d62dbccfac573e5d723f43a
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6747
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com>
Community-CI: Mellanox Build Bot
This commit is contained in:
Ben Walker 2021-03-05 10:52:30 -07:00 committed by Tomasz Zawadzki
parent 1649217a53
commit fc551b3a62

View File

@ -75,10 +75,12 @@ struct spdk_posix_sock {
TAILQ_ENTRY(spdk_posix_sock) link;
};
TAILQ_HEAD(spdk_pending_recv_list, spdk_posix_sock);
struct spdk_posix_sock_group_impl {
struct spdk_sock_group_impl base;
int fd;
TAILQ_HEAD(, spdk_posix_sock) pending_recv;
struct spdk_pending_recv_list pending_recv;
};
static struct spdk_sock_impl_opts g_spdk_posix_sock_impl_opts = {
@ -1242,6 +1244,8 @@ posix_sock_group_impl_poll(struct spdk_sock_group_impl *_group, int max_events,
}
}
assert(max_events > 0);
#if defined(SPDK_EPOLL)
num_events = epoll_wait(group->fd, events, max_events, 0);
#elif defined(SPDK_KEVENT)
@ -1314,14 +1318,35 @@ posix_sock_group_impl_poll(struct spdk_sock_group_impl *_group, int max_events,
}
/* Cycle the pending_recv list so that each time we poll things aren't
* in the same order.
* TODO: This could be done with a single operation because psock points
* to the last node that needs to get cycled already. */
for (i = 0; i < num_events; i++) {
psock = __posix_sock(socks[i]);
* in the same order. Say we have 6 sockets in the list, named as follows:
* A B C D E F
* And all 6 sockets had epoll events, but max_events is only 3. That means
* psock currently points at D. We want to rearrange the list to the following:
* D E F A B C
*
* The variables below are named according to this example to make it easier to
* follow the swaps.
*/
if (psock != NULL) {
struct spdk_posix_sock *pa, *pc, *pd, *pf;
TAILQ_REMOVE(&group->pending_recv, psock, link);
TAILQ_INSERT_TAIL(&group->pending_recv, psock, link);
/* Capture pointers to the elements we need */
pd = psock;
pc = TAILQ_PREV(pd, spdk_pending_recv_list, link);
pa = TAILQ_FIRST(&group->pending_recv);
pf = TAILQ_LAST(&group->pending_recv, spdk_pending_recv_list);
/* Break the link between C and D */
pc->link.tqe_next = NULL;
pd->link.tqe_prev = NULL;
/* Connect F to A */
pf->link.tqe_next = pa;
pa->link.tqe_prev = &pf->link.tqe_next;
/* Fix up the list first/last pointers */
group->pending_recv.tqh_first = pd;
group->pending_recv.tqh_last = &pc->link.tqe_next;
}
return num_events;