Commit 86a21aee authored by Ben Walker's avatar Ben Walker Committed by Jim Harris
Browse files

event: Implement context switch monitor without a poller



This is much simpler and avoids the problems with requiring
it to run on a thread.

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


Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
parent 3569ea15
Loading
Loading
Loading
Loading
+18 −48
Original line number Diff line number Diff line
@@ -162,10 +162,11 @@ _spdk_event_queue_run_batch(struct spdk_reactor *reactor, struct spdk_thread *th
	return count;
}

#define CONTEXT_SWITCH_MONITOR_PERIOD 1000000

static int
get_rusage(void *arg)
get_rusage(struct spdk_reactor *reactor)
{
	struct spdk_reactor	*reactor = arg;
	struct rusage		rusage;

	if (getrusage(RUSAGE_THREAD, &rusage) != 0) {
@@ -183,46 +184,14 @@ get_rusage(void *arg)
	return -1;
}

static void
_spdk_reactor_context_switch_monitor_start(void *arg1, void *arg2)
{
	struct spdk_reactor *reactor = arg1;

	if (reactor->rusage_poller == NULL) {
		getrusage(RUSAGE_THREAD, &reactor->rusage);
		reactor->rusage_poller = spdk_poller_register(get_rusage, reactor, 1000000);
	}
}

static void
_spdk_reactor_context_switch_monitor_stop(void *arg1, void *arg2)
{
	struct spdk_reactor *reactor = arg1;

	if (reactor->rusage_poller != NULL) {
		spdk_poller_unregister(&reactor->rusage_poller);
	}
}

void
spdk_reactor_enable_context_switch_monitor(bool enable)
{
	struct spdk_reactor *reactor;
	spdk_event_fn fn;
	uint32_t core;

	if (enable != g_context_switch_monitor_enabled) {
	/* This global is being read by multiple threads, so this isn't
	 * strictly thread safe. However, we're toggling between true and
	 * false here, and if a thread sees the value update later than it
	 * should, it's no big deal. */
	g_context_switch_monitor_enabled = enable;
		if (enable) {
			fn = _spdk_reactor_context_switch_monitor_start;
		} else {
			fn = _spdk_reactor_context_switch_monitor_stop;
		}
		SPDK_ENV_FOREACH_CORE(core) {
			reactor = spdk_reactor_get(core);
			spdk_event_call(spdk_event_allocate(core, fn, reactor, NULL));
		}
	}
}

bool
@@ -236,6 +205,7 @@ _spdk_reactor_run(void *arg)
{
	struct spdk_reactor	*reactor = arg;
	struct spdk_thread	*thread;
	uint64_t		last_rusage = 0;
	char			thread_name[32];

	snprintf(thread_name, sizeof(thread_name), "reactor_%u", reactor->lcore);
@@ -245,12 +215,6 @@ _spdk_reactor_run(void *arg)
	}
	SPDK_NOTICELOG("Reactor started on core %u\n", reactor->lcore);

	if (g_context_switch_monitor_enabled) {
		spdk_set_thread(thread);
		_spdk_reactor_context_switch_monitor_start(reactor, NULL);
		spdk_set_thread(NULL);
	}

	while (1) {
		_spdk_event_queue_run_batch(reactor, thread);

@@ -259,11 +223,17 @@ _spdk_reactor_run(void *arg)
		if (g_reactor_state != SPDK_REACTOR_STATE_RUNNING) {
			break;
		}

		if (g_context_switch_monitor_enabled) {
			uint64_t now = spdk_get_ticks();

			if ((last_rusage + CONTEXT_SWITCH_MONITOR_PERIOD) < now) {
				get_rusage(reactor);
				last_rusage = now;
			}
		}
	}

	spdk_set_thread(thread);
	_spdk_reactor_context_switch_monitor_stop(reactor, NULL);
	spdk_thread_exit(thread);
	return 0;
}