Commit e036215f authored by Ben Walker's avatar Ben Walker Committed by Darek Stojaczyk
Browse files

thread: Add a mechanism to exit a lightweight thread



Lightweight threads may now be exited by calling
spdk_thread_exit() within the thread. The framework
polling the thread can release the resources associated
with that lightweight thread by calling
spdk_thread_destroy().

Change-Id: I6586b9d22556b3874fb113ce5402c6b1f371786e
Signed-off-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/455319


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarSeth Howell <seth.howell5141@gmail.com>
Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Reviewed-by: default avatarDarek Stojaczyk <dariusz.stojaczyk@intel.com>
parent f658a867
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -147,6 +147,7 @@ spdk_fio_cleanup_thread(struct spdk_fio_thread *fio_thread)
	spdk_set_thread(fio_thread->thread);

	spdk_thread_exit(fio_thread->thread);
	spdk_thread_destroy(fio_thread->thread);
	free(fio_thread->iocq);
	free(fio_thread);
}
+13 −3
Original line number Diff line number Diff line
@@ -206,8 +206,9 @@ void spdk_thread_lib_fini(void);
struct spdk_thread *spdk_thread_create(const char *name, struct spdk_cpuset *cpumask);

/**
 * Release any resources related to the given thread and destroy it. Execution
 * continues on the current system thread after returning.
 * Mark the thread as exited, failing all future spdk_thread_poll() calls. May
 * only be called within an spdk poller or message.
 *
 *
 * \param thread The thread to destroy.
 *
@@ -216,6 +217,15 @@ struct spdk_thread *spdk_thread_create(const char *name, struct spdk_cpuset *cpu
 */
void spdk_thread_exit(struct spdk_thread *thread);

/**
 * Destroy a thread, releasing all of its resources. May only be called
 * on a thread previously marked as exited.
 *
 * \param thread The thread to destroy.
 *
 */
void spdk_thread_destroy(struct spdk_thread *thread);

/**
 * Return a pointer to this thread's context.
 *
@@ -255,7 +265,7 @@ struct spdk_thread *spdk_thread_get_from_ctx(void *ctx);
 * \param now The current time, in ticks. Optional. If 0 is passed, this
 *            function may call spdk_get_ticks() to get the current time.
 *
 * \return 1 if work was done. 0 if no work was done. -1 if unknown.
 * \return 1 if work was done. 0 if no work was done. -1 if thread has exited.
 */
int spdk_thread_poll(struct spdk_thread *thread, uint32_t max_msgs, uint64_t now);

+8 −1
Original line number Diff line number Diff line
@@ -258,6 +258,7 @@ _spdk_reactor_run(void *arg)

	while (1) {
		uint64_t now;
		int rc;

		/* For each loop through the reactor, capture the time. This time
		 * is used for all threads. */
@@ -268,7 +269,11 @@ _spdk_reactor_run(void *arg)
		TAILQ_FOREACH_SAFE(lw_thread, &reactor->threads, link, tmp) {
			thread = spdk_thread_get_from_ctx(lw_thread);

			spdk_thread_poll(thread, 0, now);
			rc = spdk_thread_poll(thread, 0, now);
			if (rc < 0) {
				TAILQ_REMOVE(&reactor->threads, lw_thread, link);
				spdk_thread_destroy(thread);
			}
		}

		if (g_reactor_state != SPDK_REACTOR_STATE_RUNNING) {
@@ -286,7 +291,9 @@ _spdk_reactor_run(void *arg)
	TAILQ_FOREACH_SAFE(lw_thread, &reactor->threads, link, tmp) {
		thread = spdk_thread_get_from_ctx(lw_thread);
		TAILQ_REMOVE(&reactor->threads, lw_thread, link);
		spdk_set_thread(thread);
		spdk_thread_exit(thread);
		spdk_thread_destroy(thread);
	}

	return 0;
+27 −1
Original line number Diff line number Diff line
@@ -105,6 +105,8 @@ struct spdk_thread {
	TAILQ_ENTRY(spdk_thread)	tailq;
	char				*name;

	bool				exit;

	struct spdk_cpuset		*cpumask;

	uint64_t			tsc_last;
@@ -330,7 +332,19 @@ spdk_set_thread(struct spdk_thread *thread)
void
spdk_thread_exit(struct spdk_thread *thread)
{
	SPDK_DEBUGLOG(SPDK_LOG_THREAD, "Freeing thread %s\n", thread->name);
	SPDK_DEBUGLOG(SPDK_LOG_THREAD, "Exit thread %s\n", thread->name);

	assert(tls_thread == thread);

	thread->exit = true;
}

void
spdk_thread_destroy(struct spdk_thread *thread)
{
	SPDK_DEBUGLOG(SPDK_LOG_THREAD, "Destroy thread %s\n", thread->name);

	assert(thread->exit == true);

	if (tls_thread == thread) {
		tls_thread = NULL;
@@ -400,6 +414,10 @@ _spdk_msg_queue_run_batch(struct spdk_thread *thread, uint32_t max_msgs)
		assert(msg != NULL);
		msg->fn(msg->arg);

		if (thread->exit) {
			break;
		}

		if (thread->msg_cache_count < SPDK_MSG_MEMPOOL_CACHE_SIZE) {
			/* Insert the messages at the head. We want to re-use the hot
			 * ones. */
@@ -459,6 +477,10 @@ spdk_thread_poll(struct spdk_thread *thread, uint32_t max_msgs, uint64_t now)
				   active_pollers_head, tailq, tmp) {
		int poller_rc;

		if (thread->exit) {
			break;
		}

		if (poller->state == SPDK_POLLER_STATE_UNREGISTERED) {
			TAILQ_REMOVE(&thread->active_pollers, poller, tailq);
			free(poller);
@@ -491,6 +513,10 @@ spdk_thread_poll(struct spdk_thread *thread, uint32_t max_msgs, uint64_t now)
	TAILQ_FOREACH_SAFE(poller, &thread->timer_pollers, tailq, tmp) {
		int timer_rc = 0;

		if (thread->exit) {
			break;
		}

		if (poller->state == SPDK_POLLER_STATE_UNREGISTERED) {
			TAILQ_REMOVE(&thread->timer_pollers, poller, tailq);
			free(poller);
+1 −0
Original line number Diff line number Diff line
@@ -106,6 +106,7 @@ free_threads(void)
	for (i = 0; i < g_ut_num_threads; i++) {
		set_thread(i);
		spdk_thread_exit(g_ut_threads[i].thread);
		spdk_thread_destroy(g_ut_threads[i].thread);
		g_ut_threads[i].thread = NULL;
	}

Loading