Commit 969b360d authored by Konrad Sztyber's avatar Konrad Sztyber Committed by Jim Harris
Browse files

thread: fd_group-based interrupts



It's now possible to register an interrupt for a whole fd_group.  The
advantage of doing this over registering an interrupt using fd_group's
fd is that the fd_group is nested in thread's fd_group, so
spdk_fd_group_wait() on thread's fd_group will trigger events of the
registered fd_group.

Signed-off-by: default avatarKonrad Sztyber <konrad.sztyber@intel.com>
Change-Id: I1b2e4e9ea0b5dc2a8ba5e7ab7366fe1c412167f5
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/25466


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarJim Harris <jim.harris@nvidia.com>
Reviewed-by: default avatarBen Walker <ben@nvidia.com>
Community-CI: Community CI Samsung <spdk.community.ci.samsung@gmail.com>
Community-CI: Mellanox Build Bot
Reviewed-by: default avatarAnkit Kumar <ankit.kumar@samsung.com>
parent 851f166e
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -924,6 +924,17 @@ struct spdk_interrupt *spdk_interrupt_register_ext(int efd, spdk_interrupt_fn fn
#define SPDK_INTERRUPT_REGISTER_EXT(efd, fn, arg, opts)	\
	spdk_interrupt_register_ext(efd, fn, arg, #fn, opts)

/**
 * Register an interrupt listening for all events associated with an fd_group on current thread.
 *
 * \param fgrp fd_group describing the events to listen for.
 * \param name Name of the interrupt.
 *
 * return Pointer to spdk_interrupt or NULL in case of failure.
 */
struct spdk_interrupt *spdk_interrupt_register_fd_group(struct spdk_fd_group *fgrp,
		const char *name);

/**
 * Unregister an spdk_interrupt on the current thread.
 *
+1 −0
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@
	spdk_interrupt_register_ext;
	spdk_interrupt_unregister;
	spdk_interrupt_set_event_types;
	spdk_interrupt_register_fd_group;
	spdk_thread_get_interrupt_fd;
	spdk_thread_get_interrupt_fd_group;
	spdk_interrupt_mode_enable;
+68 −3
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ static struct spdk_thread *g_app_thread;

struct spdk_interrupt {
	int			efd;
	struct spdk_fd_group	*fgrp;
	struct spdk_thread	*thread;
	spdk_interrupt_fn	fn;
	void			*arg;
@@ -2881,7 +2882,8 @@ spdk_interrupt_register_for_events(int efd, uint32_t events, spdk_interrupt_fn f
}

static struct spdk_interrupt *
alloc_interrupt(int efd, spdk_interrupt_fn fn, void *arg, const char *name)
alloc_interrupt(int efd, struct spdk_fd_group *fgrp, spdk_interrupt_fn fn, void *arg,
		const char *name)
{
	struct spdk_thread *thread;
	struct spdk_interrupt *intr;
@@ -2909,7 +2911,9 @@ alloc_interrupt(int efd, spdk_interrupt_fn fn, void *arg, const char *name)
		snprintf(intr->name, sizeof(intr->name), "%p", fn);
	}

	assert(efd < 0 || fgrp == NULL);
	intr->efd = efd;
	intr->fgrp = fgrp;
	intr->thread = thread;
	intr->fn = fn;
	intr->arg = arg;
@@ -2924,7 +2928,7 @@ spdk_interrupt_register_ext(int efd, spdk_interrupt_fn fn, void *arg, const char
	struct spdk_interrupt *intr;
	int ret;

	intr = alloc_interrupt(efd, fn, arg, name);
	intr = alloc_interrupt(efd, NULL, fn, arg, name);
	if (intr == NULL) {
		return NULL;
	}
@@ -2941,6 +2945,55 @@ spdk_interrupt_register_ext(int efd, spdk_interrupt_fn fn, void *arg, const char
	return intr;
}

static int
interrupt_fd_group_wrapper(void *wrap_ctx, spdk_fd_fn cb_fn, void *cb_ctx)
{
	struct spdk_interrupt *intr = wrap_ctx;
	struct spdk_thread *orig_thread, *thread;
	int rc;

	orig_thread = spdk_get_thread();
	thread = intr->thread;

	spdk_set_thread(thread);
	rc = cb_fn(cb_ctx);
	SPIN_ASSERT(thread->lock_count == 0, SPIN_ERR_HOLD_DURING_SWITCH);
	spdk_set_thread(orig_thread);

	return rc;
}

struct spdk_interrupt *
spdk_interrupt_register_fd_group(struct spdk_fd_group *fgrp, const char *name)
{
	struct spdk_interrupt *intr;
	int rc;

	intr = alloc_interrupt(-1, fgrp, NULL, NULL, name);
	if (intr == NULL) {
		return NULL;
	}

	rc = spdk_fd_group_set_wrapper(fgrp, interrupt_fd_group_wrapper, intr);
	if (rc != 0) {
		SPDK_ERRLOG("thread %s: failed to set wrapper for fd_group %d: %s\n",
			    intr->thread->name, spdk_fd_group_get_fd(fgrp), spdk_strerror(-rc));
		free(intr);
		return NULL;
	}

	rc = spdk_fd_group_nest(intr->thread->fgrp, fgrp);
	if (rc != 0) {
		SPDK_ERRLOG("thread %s: failed to nest fd_group %d: %s\n",
			    intr->thread->name, spdk_fd_group_get_fd(fgrp), spdk_strerror(-rc));
		spdk_fd_group_set_wrapper(fgrp, NULL, NULL);
		free(intr);
		return NULL;
	}

	return intr;
}

void
spdk_interrupt_unregister(struct spdk_interrupt **pintr)
{
@@ -2965,7 +3018,14 @@ spdk_interrupt_unregister(struct spdk_interrupt **pintr)
		return;
	}

	if (intr->fgrp != NULL) {
		assert(intr->efd < 0);
		spdk_fd_group_unnest(thread->fgrp, intr->fgrp);
		spdk_fd_group_set_wrapper(thread->fgrp, NULL, NULL);
	} else {
		spdk_fd_group_remove(thread->fgrp, intr->efd);
	}

	free(intr);
}

@@ -2986,6 +3046,11 @@ spdk_interrupt_set_event_types(struct spdk_interrupt *intr,
		return -EINVAL;
	}

	if (intr->efd < 0) {
		assert(false);
		return -EINVAL;
	}

	return spdk_fd_group_event_modify(thread->fgrp, intr->efd, event_types);
}