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;
}
#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;
}