ut_multithread: add the support of periodic poller

This patch is to add the support of periodically
running poller. A setting is added for the increased
time so that the poller on that thread can be running
or not depending on the required setting.

UT code also added for this new functionality.

Change-Id: I0d012ddb18c9b0f6ae8aa877a30d214d6ba34946
Signed-off-by: GangCao <gang.cao@intel.com>
Reviewed-on: https://review.gerrithub.io/398359
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
This commit is contained in:
GangCao 2018-02-04 18:50:57 -05:00 committed by Daniel Verkamp
parent c95cd19fbe
commit 0f2ef7cf22
2 changed files with 137 additions and 2 deletions

View File

@ -36,11 +36,14 @@
#include "spdk_internal/mock.h"
static uint32_t g_ut_num_threads;
static uint64_t g_current_time_in_us = 0;
int allocate_threads(int num_threads);
void free_threads(void);
void poll_threads(void);
int poll_thread(uintptr_t thread_id);
void increment_time(uint64_t time_in_us);
void reset_time(void);
struct ut_msg {
spdk_thread_fn fn;
@ -61,6 +64,8 @@ struct ut_poller {
spdk_poller_fn fn;
void *arg;
TAILQ_ENTRY(ut_poller) tailq;
uint64_t period_us;
uint64_t next_expiration_in_us;
};
static void
@ -87,6 +92,8 @@ __start_poller(void *thread_ctx, spdk_thread_fn fn, void *arg, uint64_t period_m
poller->fn = fn;
poller->arg = arg;
poller->period_us = period_microseconds;
poller->next_expiration_in_us = g_current_time_in_us + poller->period_us;
TAILQ_INSERT_TAIL(&thread->pollers, poller, tailq);
@ -153,6 +160,41 @@ free_threads(void)
g_ut_threads = NULL;
}
void
increment_time(uint64_t time_in_us)
{
g_current_time_in_us += time_in_us;
}
static void
reset_pollers(void)
{
uint32_t i = 0;
struct ut_thread *thread = NULL;
struct ut_poller *poller = NULL;
uintptr_t original_thread_id = g_thread_id;
CU_ASSERT(g_current_time_in_us == 0);
for (i = 0; i < g_ut_num_threads; i++) {
set_thread(i);
thread = &g_ut_threads[i];
TAILQ_FOREACH(poller, &thread->pollers, tailq) {
poller->next_expiration_in_us = g_current_time_in_us + poller->period_us;
}
}
set_thread(original_thread_id);
}
void
reset_time(void)
{
g_current_time_in_us = 0;
reset_pollers();
}
int
poll_thread(uintptr_t thread_id)
{
@ -184,8 +226,16 @@ poll_thread(uintptr_t thread_id)
poller = TAILQ_FIRST(&thread->pollers);
TAILQ_REMOVE(&thread->pollers, poller, tailq);
if (poller->fn) {
poller->fn(poller->arg);
while (g_current_time_in_us >= poller->next_expiration_in_us) {
if (poller->fn) {
poller->fn(poller->arg);
}
if (poller->period_us == 0) {
break;
} else {
poller->next_expiration_in_us += poller->period_us;
}
}
TAILQ_INSERT_TAIL(&tmp_pollers, poller, tailq);

View File

@ -269,6 +269,90 @@ basic(void)
teardown_test();
}
static void
poller_run_done(void *ctx)
{
bool *poller_run = ctx;
*poller_run = true;
}
static void
poller_run_times_done(void *ctx)
{
int *poller_run_times = ctx;
(*poller_run_times)++;
}
static void
basic_poller(void)
{
struct spdk_poller *poller = NULL;
bool poller_run = false;
int poller_run_times = 0;
setup_test();
set_thread(0);
reset_time();
/* Register a poller with no-wait time and test execution */
poller = spdk_poller_register(poller_run_done, &poller_run, 0);
CU_ASSERT(poller != NULL);
poll_threads();
CU_ASSERT(poller_run == true);
spdk_poller_unregister(&poller);
CU_ASSERT(poller == NULL);
/* Register a poller with 1000us wait time and test single execution */
poller_run = false;
poller = spdk_poller_register(poller_run_done, &poller_run, 1000);
CU_ASSERT(poller != NULL);
poll_threads();
CU_ASSERT(poller_run == false);
increment_time(1000);
poll_threads();
CU_ASSERT(poller_run == true);
reset_time();
poller_run = false;
poll_threads();
CU_ASSERT(poller_run == false);
increment_time(1000);
poll_threads();
CU_ASSERT(poller_run == true);
spdk_poller_unregister(&poller);
CU_ASSERT(poller == NULL);
reset_time();
/* Register a poller with 1000us wait time and test multiple execution */
poller = spdk_poller_register(poller_run_times_done, &poller_run_times, 1000);
CU_ASSERT(poller != NULL);
poll_threads();
CU_ASSERT(poller_run_times == 0);
increment_time(1000);
poll_threads();
CU_ASSERT(poller_run_times == 1);
poller_run_times = 0;
increment_time(2000);
poll_threads();
CU_ASSERT(poller_run_times == 2);
spdk_poller_unregister(&poller);
CU_ASSERT(poller == NULL);
teardown_test();
}
static void
reset_done(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
{
@ -689,6 +773,7 @@ main(int argc, char **argv)
if (
CU_add_test(suite, "basic", basic) == NULL ||
CU_add_test(suite, "basic_poller", basic_poller) == NULL ||
CU_add_test(suite, "put_channel_during_reset", put_channel_during_reset) == NULL ||
CU_add_test(suite, "aborted_reset", aborted_reset) == NULL ||
CU_add_test(suite, "io_during_reset", io_during_reset) == NULL ||