lib/event: fix tsc_last for first thread on reactor

tsc_last value is used to update thread stats
during _reactor_run(). See:
spdk_thread_poll(thread, 0, reactor->tsc_last);

If no threads were present on the reactor,
this value got outdated and resulted in
adding time reactor spent with no threads to
stats of the first thread placed on that reactor.

This patch fixes thread stats by making sure
that argument to spdk_thread_poll() is up to date.

Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Change-Id: I0c35fdba1b63b6ee19a5a2b34751090839cb2438
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7845
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com>
Reviewed-by: Konrad Sztyber <konrad.sztyber@intel.com>
This commit is contained in:
Tomasz Zawadzki 2021-05-07 12:52:05 -04:00
parent 320fdaa325
commit 7438c388a0
2 changed files with 52 additions and 2 deletions

View File

@ -901,6 +901,14 @@ _reactor_run(struct spdk_reactor *reactor)
event_queue_run_batch(reactor);
/* If no threads are present on the reactor,
* tsc_last gets outdated. Update it to track
* thread execution time correctly. */
if (spdk_unlikely(TAILQ_EMPTY(&reactor->threads))) {
reactor->tsc_last = spdk_get_ticks();
return;
}
TAILQ_FOREACH_SAFE(lw_thread, &reactor->threads, link, tmp) {
thread = spdk_thread_get_from_ctx(lw_thread);
rc = spdk_thread_poll(thread, 0, reactor->tsc_last);

View File

@ -374,6 +374,15 @@ test_reactor_stats(void)
* - both elapsed TSC of thread1 and thread2 should be 1100 (= 100 + 1000).
* - busy TSC of reactor should be 500 (= 100 + 400).
* - idle TSC of reactor should be 500 (= 200 + 300).
*
* After that reactor0 runs with no threads for 900 TSC.
* Create thread1 on reactor0 at TSC = 2000.
* Reactor runs
* - thread1 for 100 with busy
* Then,
* - elapsed TSC of thread1 should be 2100 (= 2000+ 100).
* - busy TSC of reactor should be 600 (= 500 + 100).
* - idle TSC of reactor should be 500 (= 500 + 0).
*/
MOCK_SET(spdk_env_get_current_core, 0);
@ -463,10 +472,43 @@ test_reactor_stats(void)
_reactor_run(reactor);
/* After 900 ticks new thread is created. */
/* 1100 + 900 = 2000 ticks elapsed */
MOCK_SET(spdk_get_ticks, 2000);
_reactor_run(reactor);
CU_ASSERT(reactor->tsc_last == 2000);
thread1 = spdk_thread_create(NULL, &cpuset);
SPDK_CU_ASSERT_FATAL(thread1 != NULL);
spdk_set_thread(thread1);
busy1 = spdk_poller_register(poller_run_busy, (void *)100, 0);
CU_ASSERT(busy1 != NULL);
_reactor_run(reactor);
spdk_set_thread(thread1);
CU_ASSERT(spdk_thread_get_last_tsc(thread1) == 2100);
CU_ASSERT(spdk_thread_get_stats(&stats) == 0);
CU_ASSERT(stats.busy_tsc == 100);
CU_ASSERT(stats.idle_tsc == 0);
CU_ASSERT(reactor->busy_tsc == 600);
CU_ASSERT(reactor->idle_tsc == 500);
/* 2000 + 100 = 2100 ticks elapsed */
CU_ASSERT(reactor->tsc_last == 2100);
spdk_set_thread(thread1);
spdk_poller_unregister(&busy1);
spdk_thread_exit(thread1);
_reactor_run(reactor);
CU_ASSERT(TAILQ_EMPTY(&reactor->threads));
/* No further than 1100 ticks elapsed */
CU_ASSERT(reactor->tsc_last == 1100);
/* No further than 2100 ticks elapsed */
CU_ASSERT(reactor->tsc_last == 2100);
spdk_reactors_fini();