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: Ben Walker <benjamin.walker@intel.com>
Reviewed-on: https://review.gerrithub.io/c/443645
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
Ben Walker 2019-02-06 14:57:44 -07:00 committed by Jim Harris
parent 3569ea154a
commit 86a21aee4e

View File

@ -162,10 +162,11 @@ _spdk_event_queue_run_batch(struct spdk_reactor *reactor, struct spdk_thread *th
return count; return count;
} }
#define CONTEXT_SWITCH_MONITOR_PERIOD 1000000
static int static int
get_rusage(void *arg) get_rusage(struct spdk_reactor *reactor)
{ {
struct spdk_reactor *reactor = arg;
struct rusage rusage; struct rusage rusage;
if (getrusage(RUSAGE_THREAD, &rusage) != 0) { if (getrusage(RUSAGE_THREAD, &rusage) != 0) {
@ -183,46 +184,14 @@ get_rusage(void *arg)
return -1; 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 void
spdk_reactor_enable_context_switch_monitor(bool enable) spdk_reactor_enable_context_switch_monitor(bool enable)
{ {
struct spdk_reactor *reactor; /* This global is being read by multiple threads, so this isn't
spdk_event_fn fn; * strictly thread safe. However, we're toggling between true and
uint32_t core; * false here, and if a thread sees the value update later than it
* should, it's no big deal. */
if (enable != g_context_switch_monitor_enabled) {
g_context_switch_monitor_enabled = enable; 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 bool
@ -236,6 +205,7 @@ _spdk_reactor_run(void *arg)
{ {
struct spdk_reactor *reactor = arg; struct spdk_reactor *reactor = arg;
struct spdk_thread *thread; struct spdk_thread *thread;
uint64_t last_rusage = 0;
char thread_name[32]; char thread_name[32];
snprintf(thread_name, sizeof(thread_name), "reactor_%u", reactor->lcore); 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); 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) { while (1) {
_spdk_event_queue_run_batch(reactor, thread); _spdk_event_queue_run_batch(reactor, thread);
@ -259,11 +223,17 @@ _spdk_reactor_run(void *arg)
if (g_reactor_state != SPDK_REACTOR_STATE_RUNNING) { if (g_reactor_state != SPDK_REACTOR_STATE_RUNNING) {
break; 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; return 0;
} }