thread: Run all pollers on each spdk_thread_poll call

This prevents issues where spdk_thread_poll may report
that it did not useful work (for the one poller it ran),
causing the system thread to go to sleep.

Change-Id: I7a4842d5e399758c19268aee343a001ccfc88a3a
Signed-off-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-on: https://review.gerrithub.io/c/440598
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
This commit is contained in:
Ben Walker 2019-01-15 14:35:46 -07:00 committed by Darek Stojaczyk
parent 06cc80459f
commit 836356f2d5

View File

@ -121,7 +121,7 @@ struct spdk_thread {
* of the ring, executes it, then puts it back at the tail of
* the ring.
*/
TAILQ_HEAD(, spdk_poller) active_pollers;
TAILQ_HEAD(active_pollers_head, spdk_poller) active_pollers;
/**
* Contains pollers running on this thread with a periodic timer.
@ -264,6 +264,7 @@ spdk_thread_exit(struct spdk_thread *thread)
{
struct spdk_io_channel *ch;
struct spdk_msg *msg;
struct spdk_poller *poller, *ptmp;
SPDK_DEBUGLOG(SPDK_LOG_THREAD, "Freeing thread %s\n", thread->name);
@ -276,6 +277,27 @@ spdk_thread_exit(struct spdk_thread *thread)
thread->name, ch->dev->name);
}
TAILQ_FOREACH_SAFE(poller, &thread->active_pollers, tailq, ptmp) {
if (poller->state == SPDK_POLLER_STATE_WAITING) {
SPDK_WARNLOG("poller %p still registered at thread exit\n",
poller);
}
TAILQ_REMOVE(&thread->active_pollers, poller, tailq);
free(poller);
}
TAILQ_FOREACH_SAFE(poller, &thread->timer_pollers, tailq, ptmp) {
if (poller->state == SPDK_POLLER_STATE_WAITING) {
SPDK_WARNLOG("poller %p still registered at thread exit\n",
poller);
}
TAILQ_REMOVE(&thread->timer_pollers, poller, tailq);
free(poller);
}
pthread_mutex_lock(&g_devlist_mutex);
assert(g_thread_count > 0);
g_thread_count--;
@ -376,7 +398,7 @@ spdk_thread_poll(struct spdk_thread *thread, uint32_t max_msgs, uint64_t now)
{
uint32_t msg_count;
struct spdk_thread *orig_thread;
struct spdk_poller *poller;
struct spdk_poller *poller, *tmp;
int rc = 0;
orig_thread = _get_thread();
@ -391,20 +413,27 @@ spdk_thread_poll(struct spdk_thread *thread, uint32_t max_msgs, uint64_t now)
rc = 1;
}
poller = TAILQ_FIRST(&thread->active_pollers);
if (poller) {
TAILQ_FOREACH_REVERSE_SAFE(poller, &thread->active_pollers,
active_pollers_head, tailq, tmp) {
int poller_rc;
if (poller->state == SPDK_POLLER_STATE_UNREGISTERED) {
TAILQ_REMOVE(&thread->active_pollers, poller, tailq);
free(poller);
continue;
}
poller->state = SPDK_POLLER_STATE_RUNNING;
poller_rc = poller->fn(poller->arg);
if (poller->state == SPDK_POLLER_STATE_UNREGISTERED) {
TAILQ_REMOVE(&thread->active_pollers, poller, tailq);
free(poller);
} else {
poller->state = SPDK_POLLER_STATE_WAITING;
TAILQ_INSERT_TAIL(&thread->active_pollers, poller, tailq);
continue;
}
poller->state = SPDK_POLLER_STATE_WAITING;
#ifdef DEBUG
if (poller_rc == -1) {
SPDK_DEBUGLOG(SPDK_LOG_THREAD, "Poller %p returned -1\n", poller);
@ -414,23 +443,35 @@ spdk_thread_poll(struct spdk_thread *thread, uint32_t max_msgs, uint64_t now)
if (poller_rc > rc) {
rc = poller_rc;
}
}
poller = TAILQ_FIRST(&thread->timer_pollers);
if (poller) {
if (now >= poller->next_run_tick) {
TAILQ_FOREACH_SAFE(poller, &thread->timer_pollers, tailq, tmp) {
int timer_rc = 0;
if (poller->state == SPDK_POLLER_STATE_UNREGISTERED) {
TAILQ_REMOVE(&thread->timer_pollers, poller, tailq);
free(poller);
continue;
}
if (now < poller->next_run_tick) {
break;
}
poller->state = SPDK_POLLER_STATE_RUNNING;
timer_rc = poller->fn(poller->arg);
if (poller->state == SPDK_POLLER_STATE_UNREGISTERED) {
TAILQ_REMOVE(&thread->timer_pollers, poller, tailq);
free(poller);
} else {
poller->state = SPDK_POLLER_STATE_WAITING;
_spdk_poller_insert_timer(thread, poller, now);
continue;
}
poller->state = SPDK_POLLER_STATE_WAITING;
TAILQ_REMOVE(&thread->timer_pollers, poller, tailq);
_spdk_poller_insert_timer(thread, poller, now);
#ifdef DEBUG
if (timer_rc == -1) {
SPDK_DEBUGLOG(SPDK_LOG_THREAD, "Timed poller %p returned -1\n", poller);
@ -442,7 +483,6 @@ spdk_thread_poll(struct spdk_thread *thread, uint32_t max_msgs, uint64_t now)
}
}
}
if (rc == 0) {
/* Poller status idle */
@ -636,22 +676,10 @@ spdk_poller_unregister(struct spdk_poller **ppoller)
return;
}
if (poller->state == SPDK_POLLER_STATE_RUNNING) {
/*
* We are being called from the poller_fn, so set the state to unregistered
* and let the thread poll loop free the poller.
/* Simply set the state to unregistered. The poller will get cleaned up
* in a subsequent call to spdk_thread_poll().
*/
poller->state = SPDK_POLLER_STATE_UNREGISTERED;
} else {
/* Poller is not running currently, so just free it. */
if (poller->period_ticks) {
TAILQ_REMOVE(&thread->timer_pollers, poller, tailq);
} else {
TAILQ_REMOVE(&thread->active_pollers, poller, tailq);
}
free(poller);
}
}
struct call_thread {