reactor: add context_switch_monitor RPC
This allows the user to enable/disable getrusage() monitoring at runtime. Also change the log level to INFO and enable the monitoring in all builds, not just #ifdef DEBUG. Change-Id: I2f5c3bc8cd83dcb2a72dc7078bf2cb43aa28827c Signed-off-by: Daniel Verkamp <daniel.verkamp@intel.com> Reviewed-on: https://review.gerrithub.io/376473 Tested-by: SPDK Automated Test System <sys_sgsw@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Cunyin Chang <cunyin.chang@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
parent
491a44a71c
commit
70c3e1f2eb
@ -176,4 +176,14 @@ void spdk_poller_register(struct spdk_poller **ppoller,
|
||||
void spdk_poller_unregister(struct spdk_poller **ppoller,
|
||||
struct spdk_event *complete);
|
||||
|
||||
/**
|
||||
* \brief Enable or disable monitoring of context switches.
|
||||
*/
|
||||
void spdk_reactor_enable_context_switch_monitor(bool enabled);
|
||||
|
||||
/**
|
||||
* \brief Return whether context switch monitoring is enabled.
|
||||
*/
|
||||
bool spdk_reactor_context_switch_monitor_enabled(void);
|
||||
|
||||
#endif
|
||||
|
@ -87,13 +87,13 @@ struct spdk_reactor {
|
||||
|
||||
/* Socket ID for this reactor. */
|
||||
uint32_t socket_id;
|
||||
#ifdef DEBUG
|
||||
|
||||
/* Poller for get the rusage for the reactor. */
|
||||
struct spdk_poller *rusage_poller;
|
||||
|
||||
/* The last known rusage values */
|
||||
struct rusage rusage;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Contains pollers actively running on this reactor. Pollers
|
||||
* are run round-robin. The reactor takes one poller from the head
|
||||
@ -119,6 +119,8 @@ static struct spdk_reactor g_reactors[SPDK_MAX_REACTORS];
|
||||
|
||||
static enum spdk_reactor_state g_reactor_state = SPDK_REACTOR_STATE_INVALID;
|
||||
|
||||
static bool g_context_switch_monitor_enabled = true;
|
||||
|
||||
static void spdk_reactor_construct(struct spdk_reactor *w, uint32_t lcore,
|
||||
uint64_t max_delay_us);
|
||||
|
||||
@ -254,7 +256,6 @@ _spdk_reactor_send_msg(spdk_thread_fn fn, void *ctx, void *thread_ctx)
|
||||
spdk_event_call(event);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static void
|
||||
get_rusage(void *arg)
|
||||
{
|
||||
@ -266,14 +267,61 @@ get_rusage(void *arg)
|
||||
}
|
||||
|
||||
if (rusage.ru_nvcsw != reactor->rusage.ru_nvcsw || rusage.ru_nivcsw != reactor->rusage.ru_nivcsw) {
|
||||
SPDK_DEBUGLOG(SPDK_TRACE_REACTOR,
|
||||
"Reactor %d: %ld voluntary context switches and %ld involuntary context switches in the last second.\n",
|
||||
reactor->lcore, rusage.ru_nvcsw - reactor->rusage.ru_nvcsw,
|
||||
rusage.ru_nivcsw - reactor->rusage.ru_nivcsw);
|
||||
SPDK_INFOLOG(SPDK_TRACE_REACTOR,
|
||||
"Reactor %d: %ld voluntary context switches and %ld involuntary context switches in the last second.\n",
|
||||
reactor->lcore, rusage.ru_nvcsw - reactor->rusage.ru_nvcsw,
|
||||
rusage.ru_nivcsw - reactor->rusage.ru_nivcsw);
|
||||
}
|
||||
reactor->rusage = rusage;
|
||||
}
|
||||
#endif
|
||||
|
||||
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);
|
||||
spdk_poller_register(&reactor->rusage_poller, get_rusage, reactor, reactor->lcore, 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, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
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
|
||||
spdk_reactor_context_switch_monitor_enabled(void)
|
||||
{
|
||||
return g_context_switch_monitor_enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
@ -317,10 +365,9 @@ _spdk_reactor_run(void *arg)
|
||||
sleep_cycles = reactor->max_delay_us * spdk_get_ticks_hz() / 1000000ULL;
|
||||
idle_started = 0;
|
||||
timer_poll_count = 0;
|
||||
#ifdef DEBUG
|
||||
getrusage(RUSAGE_THREAD, &reactor->rusage);
|
||||
spdk_poller_register(&reactor->rusage_poller, get_rusage, reactor, reactor->lcore, 1000000);
|
||||
#endif
|
||||
if (g_context_switch_monitor_enabled) {
|
||||
_spdk_reactor_context_switch_monitor_start(reactor, NULL);
|
||||
}
|
||||
while (1) {
|
||||
bool took_action = false;
|
||||
|
||||
@ -403,13 +450,11 @@ _spdk_reactor_run(void *arg)
|
||||
}
|
||||
|
||||
if (g_reactor_state != SPDK_REACTOR_STATE_RUNNING) {
|
||||
#ifdef DEBUG
|
||||
spdk_poller_unregister(&reactor->rusage_poller, NULL);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_spdk_reactor_context_switch_monitor_stop(reactor, NULL);
|
||||
spdk_free_thread();
|
||||
return 0;
|
||||
}
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
#include "spdk/stdinc.h"
|
||||
|
||||
#include "spdk/event.h"
|
||||
#include "spdk/rpc.h"
|
||||
#include "spdk/util.h"
|
||||
|
||||
@ -108,3 +109,47 @@ invalid:
|
||||
free_rpc_kill_instance(&req);
|
||||
}
|
||||
SPDK_RPC_REGISTER("kill_instance", spdk_rpc_kill_instance)
|
||||
|
||||
|
||||
struct rpc_context_switch_monitor {
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
static const struct spdk_json_object_decoder rpc_context_switch_monitor_decoders[] = {
|
||||
{"enabled", offsetof(struct rpc_context_switch_monitor, enabled), spdk_json_decode_bool},
|
||||
};
|
||||
|
||||
static void
|
||||
spdk_rpc_context_switch_monitor(struct spdk_jsonrpc_request *request,
|
||||
const struct spdk_json_val *params)
|
||||
{
|
||||
struct rpc_context_switch_monitor req = {};
|
||||
struct spdk_json_write_ctx *w;
|
||||
|
||||
if (params != NULL) {
|
||||
if (spdk_json_decode_object(params, rpc_context_switch_monitor_decoders,
|
||||
SPDK_COUNTOF(rpc_context_switch_monitor_decoders),
|
||||
&req)) {
|
||||
SPDK_DEBUGLOG(SPDK_TRACE_REACTOR, "spdk_json_decode_object failed\n");
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
|
||||
return;
|
||||
}
|
||||
|
||||
spdk_reactor_enable_context_switch_monitor(req.enabled);
|
||||
}
|
||||
|
||||
w = spdk_jsonrpc_begin_result(request);
|
||||
if (w == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
spdk_json_write_object_begin(w);
|
||||
|
||||
spdk_json_write_name(w, "enabled");
|
||||
spdk_json_write_bool(w, spdk_reactor_context_switch_monitor_enabled());
|
||||
|
||||
spdk_json_write_object_end(w);
|
||||
spdk_jsonrpc_end_result(request, w);
|
||||
}
|
||||
|
||||
SPDK_RPC_REGISTER("context_switch_monitor", spdk_rpc_context_switch_monitor)
|
||||
|
@ -564,5 +564,18 @@ def get_rpc_methods(args):
|
||||
p = subparsers.add_parser('get_rpc_methods', help='Get list of supported RPC methods')
|
||||
p.set_defaults(func=get_rpc_methods)
|
||||
|
||||
def context_switch_monitor(args):
|
||||
params = {}
|
||||
if args.enable:
|
||||
params['enabled'] = True
|
||||
if args.disable:
|
||||
params['enabled'] = False
|
||||
print_dict(jsonrpc_call('context_switch_monitor', params))
|
||||
|
||||
p = subparsers.add_parser('context_switch_monitor', help='Control whether the context switch monitor is enabled')
|
||||
p.add_argument('-e', '--enable', action='store_true', help='Enable context switch monitoring')
|
||||
p.add_argument('-d', '--disable', action='store_true', help='Disable context switch monitoring')
|
||||
p.set_defaults(func=context_switch_monitor)
|
||||
|
||||
args = parser.parse_args()
|
||||
args.func(args)
|
||||
|
Loading…
Reference in New Issue
Block a user