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:
parent
06cc80459f
commit
836356f2d5
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user