Commit 0f2ef7cf authored by GangCao's avatar GangCao Committed by Daniel Verkamp
Browse files

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: default avatarGangCao <gang.cao@intel.com>
Reviewed-on: https://review.gerrithub.io/398359


Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
parent c95cd19f
Loading
Loading
Loading
Loading
+52 −2
Original line number Diff line number Diff line
@@ -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,10 +226,18 @@ poll_thread(uintptr_t thread_id)
		poller = TAILQ_FIRST(&thread->pollers);
		TAILQ_REMOVE(&thread->pollers, poller, tailq);

		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);
	}

+85 −0
Original line number Diff line number Diff line
@@ -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 ||