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 * of the ring, executes it, then puts it back at the tail of
* the ring. * 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. * 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_io_channel *ch;
struct spdk_msg *msg; struct spdk_msg *msg;
struct spdk_poller *poller, *ptmp;
SPDK_DEBUGLOG(SPDK_LOG_THREAD, "Freeing thread %s\n", thread->name); 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); 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); pthread_mutex_lock(&g_devlist_mutex);
assert(g_thread_count > 0); assert(g_thread_count > 0);
g_thread_count--; 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; uint32_t msg_count;
struct spdk_thread *orig_thread; struct spdk_thread *orig_thread;
struct spdk_poller *poller; struct spdk_poller *poller, *tmp;
int rc = 0; int rc = 0;
orig_thread = _get_thread(); orig_thread = _get_thread();
@ -391,20 +413,27 @@ spdk_thread_poll(struct spdk_thread *thread, uint32_t max_msgs, uint64_t now)
rc = 1; rc = 1;
} }
poller = TAILQ_FIRST(&thread->active_pollers); TAILQ_FOREACH_REVERSE_SAFE(poller, &thread->active_pollers,
if (poller) { active_pollers_head, tailq, tmp) {
int poller_rc; int poller_rc;
if (poller->state == SPDK_POLLER_STATE_UNREGISTERED) {
TAILQ_REMOVE(&thread->active_pollers, poller, tailq); TAILQ_REMOVE(&thread->active_pollers, poller, tailq);
free(poller);
continue;
}
poller->state = SPDK_POLLER_STATE_RUNNING; poller->state = SPDK_POLLER_STATE_RUNNING;
poller_rc = poller->fn(poller->arg); poller_rc = poller->fn(poller->arg);
if (poller->state == SPDK_POLLER_STATE_UNREGISTERED) { if (poller->state == SPDK_POLLER_STATE_UNREGISTERED) {
TAILQ_REMOVE(&thread->active_pollers, poller, tailq);
free(poller); free(poller);
} else { continue;
poller->state = SPDK_POLLER_STATE_WAITING;
TAILQ_INSERT_TAIL(&thread->active_pollers, poller, tailq);
} }
poller->state = SPDK_POLLER_STATE_WAITING;
#ifdef DEBUG #ifdef DEBUG
if (poller_rc == -1) { if (poller_rc == -1) {
SPDK_DEBUGLOG(SPDK_LOG_THREAD, "Poller %p returned -1\n", poller); 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) { if (poller_rc > rc) {
rc = poller_rc; rc = poller_rc;
} }
} }
poller = TAILQ_FIRST(&thread->timer_pollers); TAILQ_FOREACH_SAFE(poller, &thread->timer_pollers, tailq, tmp) {
if (poller) {
if (now >= poller->next_run_tick) {
int timer_rc = 0; int timer_rc = 0;
if (poller->state == SPDK_POLLER_STATE_UNREGISTERED) {
TAILQ_REMOVE(&thread->timer_pollers, poller, tailq); TAILQ_REMOVE(&thread->timer_pollers, poller, tailq);
free(poller);
continue;
}
if (now < poller->next_run_tick) {
break;
}
poller->state = SPDK_POLLER_STATE_RUNNING; poller->state = SPDK_POLLER_STATE_RUNNING;
timer_rc = poller->fn(poller->arg); timer_rc = poller->fn(poller->arg);
if (poller->state == SPDK_POLLER_STATE_UNREGISTERED) { if (poller->state == SPDK_POLLER_STATE_UNREGISTERED) {
TAILQ_REMOVE(&thread->timer_pollers, poller, tailq);
free(poller); free(poller);
} else { continue;
poller->state = SPDK_POLLER_STATE_WAITING;
_spdk_poller_insert_timer(thread, poller, now);
} }
poller->state = SPDK_POLLER_STATE_WAITING;
TAILQ_REMOVE(&thread->timer_pollers, poller, tailq);
_spdk_poller_insert_timer(thread, poller, now);
#ifdef DEBUG #ifdef DEBUG
if (timer_rc == -1) { if (timer_rc == -1) {
SPDK_DEBUGLOG(SPDK_LOG_THREAD, "Timed poller %p returned -1\n", poller); 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) { if (rc == 0) {
/* Poller status idle */ /* Poller status idle */
@ -636,22 +676,10 @@ spdk_poller_unregister(struct spdk_poller **ppoller)
return; return;
} }
if (poller->state == SPDK_POLLER_STATE_RUNNING) { /* Simply set the state to unregistered. The poller will get cleaned up
/* * in a subsequent call to spdk_thread_poll().
* We are being called from the poller_fn, so set the state to unregistered
* and let the thread poll loop free the poller.
*/ */
poller->state = SPDK_POLLER_STATE_UNREGISTERED; 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 { struct call_thread {