Commit 39527e93 authored by Liu Xiaodong's avatar Liu Xiaodong Committed by Tomasz Zawadzki
Browse files

thread: refine period poller intr function



These refined functions are prepared to adapt period
poller to following poller switchable API.

Change-Id: I34d2a785fa0e757b97b0dac5ccf24819d75e0184
Signed-off-by: default avatarLiu Xiaodong <xiaodong.liu@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/7156


Reviewed-by: default avatarKonrad Sztyber <konrad.sztyber@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Mellanox Build Bot
parent b763ebfe
Loading
Loading
Loading
Loading
+66 −56
Original line number Diff line number Diff line
@@ -982,49 +982,6 @@ spdk_thread_send_critical_msg(struct spdk_thread *thread, spdk_msg_fn fn)
}

#ifdef __linux__
static int
interrupt_timerfd_prepare(uint64_t period_microseconds)
{
	int timerfd;
	int ret;
	struct itimerspec new_tv;
	uint64_t period_seconds;
	uint64_t period_nanoseconds;

	if (period_microseconds == 0) {
		return -EINVAL;
	}

	period_seconds = period_microseconds / SPDK_SEC_TO_USEC;
	period_nanoseconds = period_microseconds % SPDK_SEC_TO_USEC * 1000;

	new_tv.it_value.tv_sec = period_seconds;
	new_tv.it_value.tv_nsec = period_nanoseconds;

	new_tv.it_interval.tv_sec = period_seconds;
	new_tv.it_interval.tv_nsec = period_nanoseconds;

	timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK & TFD_CLOEXEC);
	if (timerfd < 0) {
		return -errno;
	}

	ret = timerfd_settime(timerfd, 0, &new_tv, NULL);
	if (ret < 0) {
		close(timerfd);
		return -errno;
	}

	return timerfd;
}
#else
static int
interrupt_timerfd_prepare(uint64_t period_microseconds)
{
	return -ENOTSUP;
}
#endif

static int
interrupt_timerfd_process(void *arg)
{
@@ -1045,17 +1002,25 @@ interrupt_timerfd_process(void *arg)
	return poller->fn(poller->arg);
}

static void period_poller_interrupt_fini(struct spdk_poller *poller);

static int
thread_interrupt_register_timerfd(struct spdk_fd_group *fgrp,
				  uint64_t period_microseconds,
				  struct spdk_poller *poller)
period_poller_interrupt_init(struct spdk_poller *poller)
{
	struct spdk_fd_group *fgrp = poller->thread->fgrp;
	int timerfd;
	int rc;
	uint64_t now_tick = spdk_get_ticks();
	uint64_t ticks = spdk_get_ticks_hz();
	int ret;
	struct itimerspec new_tv;

	assert(poller->period_ticks != 0);

	timerfd = interrupt_timerfd_prepare(period_microseconds);
	SPDK_DEBUGLOG(thread, "timerfd init for period poller %s\n", poller->name);
	timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
	if (timerfd < 0) {
		return timerfd;
		return -errno;
	}

	rc = spdk_fd_group_add(fgrp, timerfd,
@@ -1065,9 +1030,57 @@ thread_interrupt_register_timerfd(struct spdk_fd_group *fgrp,
		return rc;
	}

	return timerfd;
	poller->timerfd = timerfd;

	/* Set repeated timer expirations */
	new_tv.it_interval.tv_sec = poller->period_ticks / ticks;
	new_tv.it_interval.tv_nsec = poller->period_ticks % ticks * SPDK_SEC_TO_NSEC / ticks;

	/* Update next expiration */
	if (poller->next_run_tick == 0) {
		poller->next_run_tick = now_tick + poller->period_ticks;
	} else if (poller->next_run_tick < now_tick) {
		poller->next_run_tick = now_tick;
	}

	new_tv.it_value.tv_sec = (poller->next_run_tick - now_tick) / ticks;
	new_tv.it_value.tv_nsec = (poller->next_run_tick - now_tick) % ticks * SPDK_SEC_TO_NSEC / ticks;

	ret = timerfd_settime(timerfd, 0, &new_tv, NULL);
	if (ret < 0) {
		rc = -errno;
		SPDK_ERRLOG("Failed to arm timerfd: error(%d)\n", errno);
		period_poller_interrupt_fini(poller);
		return rc;
	}

	return 0;
}

static void
period_poller_interrupt_fini(struct spdk_poller *poller)
{
	SPDK_DEBUGLOG(thread, "timerfd fini for poller %s\n", poller->name);
	assert(poller->timerfd >= 0);
	spdk_fd_group_remove(poller->thread->fgrp, poller->timerfd);
	close(poller->timerfd);
	poller->timerfd = -1;
}

#else

static int
period_poller_interrupt_init(struct spdk_poller *poller)
{
	return -ENOTSUP;
}

static void
period_poller_interrupt_fini(struct spdk_poller *poller)
{
}
#endif

static struct spdk_poller *
poller_register(spdk_poller_fn fn,
		void *arg,
@@ -1105,6 +1118,7 @@ poller_register(spdk_poller_fn fn,
	poller->fn = fn;
	poller->arg = arg;
	poller->thread = thread;
	poller->timerfd = -1;

	if (period_microseconds) {
		quotient = period_microseconds / SPDK_SEC_TO_USEC;
@@ -1116,17 +1130,15 @@ poller_register(spdk_poller_fn fn,
		poller->period_ticks = 0;
	}

	if (spdk_interrupt_mode_is_enabled() && period_microseconds != 0) {
	if (period_microseconds && spdk_interrupt_mode_is_enabled()) {
		int rc;

		poller->timerfd = -1;
		rc = thread_interrupt_register_timerfd(thread->fgrp, period_microseconds, poller);
		rc = period_poller_interrupt_init(poller);
		if (rc < 0) {
			SPDK_ERRLOG("Failed to register timerfd for periodic poller: %s\n", spdk_strerror(-rc));
			free(poller);
			return NULL;
		}
		poller->timerfd = rc;
	}

	thread_insert_poller(thread, poller);
@@ -1177,9 +1189,7 @@ spdk_poller_unregister(struct spdk_poller **ppoller)
	}

	if (spdk_interrupt_mode_is_enabled() && poller->timerfd >= 0) {
		spdk_fd_group_remove(thread->fgrp, poller->timerfd);
		close(poller->timerfd);
		poller->timerfd = -1;
		period_poller_interrupt_fini(poller);
	}

	/* If the poller was paused, put it on the active_pollers list so that