LCOV - code coverage report
Current view: top level - lib/event - app_rpc.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 0 362 0.0 %
Date: 2024-07-13 05:53:56 Functions: 0 34 0.0 %

          Line data    Source code
       1             : /*   SPDX-License-Identifier: BSD-3-Clause
       2             :  *   Copyright (C) 2016 Intel Corporation. All rights reserved.
       3             :  *   Copyright (c) 2019 Mellanox Technologies LTD. All rights reserved.
       4             :  */
       5             : 
       6             : #include "spdk/stdinc.h"
       7             : 
       8             : #include "spdk/event.h"
       9             : #include "spdk/rpc.h"
      10             : #include "spdk/string.h"
      11             : #include "spdk/util.h"
      12             : #include "spdk/env.h"
      13             : #include "spdk/scheduler.h"
      14             : #include "spdk/thread.h"
      15             : #include "spdk/json.h"
      16             : 
      17             : #include "spdk/log.h"
      18             : #include "spdk_internal/event.h"
      19             : #include "spdk_internal/thread.h"
      20             : #include "event_internal.h"
      21             : 
      22             : struct rpc_spdk_kill_instance {
      23             :         char *sig_name;
      24             : };
      25             : 
      26             : static void
      27           0 : free_rpc_spdk_kill_instance(struct rpc_spdk_kill_instance *req)
      28             : {
      29           0 :         free(req->sig_name);
      30           0 : }
      31             : 
      32             : static const struct spdk_json_object_decoder rpc_spdk_kill_instance_decoders[] = {
      33             :         {"sig_name", offsetof(struct rpc_spdk_kill_instance, sig_name), spdk_json_decode_string},
      34             : };
      35             : 
      36             : static void
      37           0 : rpc_spdk_kill_instance(struct spdk_jsonrpc_request *request,
      38             :                        const struct spdk_json_val *params)
      39             : {
      40             :         static const struct {
      41             :                 const char      *signal_string;
      42             :                 int32_t         signal;
      43             :         } signals[] = {
      44             :                 {"SIGINT",    SIGINT},
      45             :                 {"SIGTERM",   SIGTERM},
      46             :                 {"SIGQUIT",   SIGQUIT},
      47             :                 {"SIGHUP",    SIGHUP},
      48             :                 {"SIGKILL",   SIGKILL},
      49             :                 {"SIGUSR1",   SIGUSR1},
      50             :         };
      51             :         size_t i, sig_count;
      52             :         int signal;
      53           0 :         struct rpc_spdk_kill_instance req = {};
      54             : 
      55           0 :         if (spdk_json_decode_object(params, rpc_spdk_kill_instance_decoders,
      56             :                                     SPDK_COUNTOF(rpc_spdk_kill_instance_decoders),
      57             :                                     &req)) {
      58           0 :                 SPDK_DEBUGLOG(app_rpc, "spdk_json_decode_object failed\n");
      59           0 :                 goto invalid;
      60             :         }
      61             : 
      62           0 :         sig_count = SPDK_COUNTOF(signals);
      63           0 :         signal = spdk_strtol(req.sig_name, 10);
      64           0 :         for (i = 0 ; i < sig_count; i++) {
      65           0 :                 if (strcmp(req.sig_name, signals[i].signal_string) == 0 ||
      66           0 :                     signal == signals[i].signal) {
      67             :                         break;
      68             :                 }
      69             :         }
      70             : 
      71           0 :         if (i == sig_count) {
      72           0 :                 goto invalid;
      73             :         }
      74             : 
      75           0 :         SPDK_DEBUGLOG(app_rpc, "sending signal %d\n", signals[i].signal);
      76           0 :         free_rpc_spdk_kill_instance(&req);
      77           0 :         kill(getpid(), signals[i].signal);
      78             : 
      79           0 :         spdk_jsonrpc_send_bool_response(request, true);
      80           0 :         return;
      81             : 
      82           0 : invalid:
      83           0 :         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
      84           0 :         free_rpc_spdk_kill_instance(&req);
      85             : }
      86           0 : SPDK_RPC_REGISTER("spdk_kill_instance", rpc_spdk_kill_instance, SPDK_RPC_RUNTIME)
      87             : 
      88             : 
      89             : struct rpc_framework_monitor_context_switch {
      90             :         bool enabled;
      91             : };
      92             : 
      93             : static const struct spdk_json_object_decoder rpc_framework_monitor_context_switch_decoders[] = {
      94             :         {"enabled", offsetof(struct rpc_framework_monitor_context_switch, enabled), spdk_json_decode_bool},
      95             : };
      96             : 
      97             : static void
      98           0 : rpc_framework_monitor_context_switch(struct spdk_jsonrpc_request *request,
      99             :                                      const struct spdk_json_val *params)
     100             : {
     101           0 :         struct rpc_framework_monitor_context_switch req = {};
     102             :         struct spdk_json_write_ctx *w;
     103             : 
     104           0 :         if (params != NULL) {
     105           0 :                 if (spdk_json_decode_object(params, rpc_framework_monitor_context_switch_decoders,
     106             :                                             SPDK_COUNTOF(rpc_framework_monitor_context_switch_decoders),
     107             :                                             &req)) {
     108           0 :                         SPDK_DEBUGLOG(app_rpc, "spdk_json_decode_object failed\n");
     109           0 :                         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
     110           0 :                         return;
     111             :                 }
     112             : 
     113           0 :                 spdk_framework_enable_context_switch_monitor(req.enabled);
     114             :         }
     115             : 
     116           0 :         w = spdk_jsonrpc_begin_result(request);
     117           0 :         spdk_json_write_object_begin(w);
     118             : 
     119           0 :         spdk_json_write_named_bool(w, "enabled", spdk_framework_context_switch_monitor_enabled());
     120             : 
     121           0 :         spdk_json_write_object_end(w);
     122           0 :         spdk_jsonrpc_end_result(request, w);
     123             : }
     124             : 
     125           0 : SPDK_RPC_REGISTER("framework_monitor_context_switch", rpc_framework_monitor_context_switch,
     126             :                   SPDK_RPC_RUNTIME)
     127             : 
     128             : struct rpc_get_stats_ctx {
     129             :         struct spdk_jsonrpc_request *request;
     130             :         struct spdk_json_write_ctx *w;
     131             :         uint64_t now;
     132             : };
     133             : 
     134             : static void
     135           0 : rpc_thread_get_stats_done(void *arg)
     136             : {
     137           0 :         struct rpc_get_stats_ctx *ctx = arg;
     138             : 
     139           0 :         spdk_json_write_array_end(ctx->w);
     140           0 :         spdk_json_write_object_end(ctx->w);
     141           0 :         spdk_jsonrpc_end_result(ctx->request, ctx->w);
     142             : 
     143           0 :         free(ctx);
     144           0 : }
     145             : 
     146             : static void
     147           0 : rpc_thread_get_stats_for_each(struct spdk_jsonrpc_request *request, spdk_msg_fn fn)
     148             : {
     149             :         struct rpc_get_stats_ctx *ctx;
     150             : 
     151           0 :         ctx = calloc(1, sizeof(*ctx));
     152           0 :         if (!ctx) {
     153           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
     154             :                                                  "Memory allocation error");
     155           0 :                 return;
     156             :         }
     157           0 :         ctx->request = request;
     158             : 
     159           0 :         ctx->w = spdk_jsonrpc_begin_result(ctx->request);
     160           0 :         spdk_json_write_object_begin(ctx->w);
     161           0 :         spdk_json_write_named_uint64(ctx->w, "tick_rate", spdk_get_ticks_hz());
     162           0 :         spdk_json_write_named_array_begin(ctx->w, "threads");
     163             : 
     164           0 :         spdk_for_each_thread(fn, ctx, rpc_thread_get_stats_done);
     165             : }
     166             : 
     167             : static void
     168           0 : _rpc_thread_get_stats(void *arg)
     169             : {
     170           0 :         struct rpc_get_stats_ctx *ctx = arg;
     171           0 :         struct spdk_thread *thread = spdk_get_thread();
     172           0 :         struct spdk_cpuset tmp_mask = {};
     173             :         struct spdk_poller *poller;
     174           0 :         struct spdk_thread_stats stats;
     175           0 :         uint64_t active_pollers_count = 0;
     176           0 :         uint64_t timed_pollers_count = 0;
     177           0 :         uint64_t paused_pollers_count = 0;
     178             : 
     179           0 :         for (poller = spdk_thread_get_first_active_poller(thread); poller != NULL;
     180           0 :              poller = spdk_thread_get_next_active_poller(poller)) {
     181           0 :                 active_pollers_count++;
     182             :         }
     183             : 
     184           0 :         for (poller = spdk_thread_get_first_timed_poller(thread); poller != NULL;
     185           0 :              poller = spdk_thread_get_next_timed_poller(poller)) {
     186           0 :                 timed_pollers_count++;
     187             :         }
     188             : 
     189           0 :         for (poller = spdk_thread_get_first_paused_poller(thread); poller != NULL;
     190           0 :              poller = spdk_thread_get_next_paused_poller(poller)) {
     191           0 :                 paused_pollers_count++;
     192             :         }
     193             : 
     194           0 :         if (0 == spdk_thread_get_stats(&stats)) {
     195           0 :                 spdk_json_write_object_begin(ctx->w);
     196           0 :                 spdk_json_write_named_string(ctx->w, "name", spdk_thread_get_name(thread));
     197           0 :                 spdk_json_write_named_uint64(ctx->w, "id", spdk_thread_get_id(thread));
     198           0 :                 spdk_cpuset_copy(&tmp_mask, spdk_app_get_core_mask());
     199           0 :                 spdk_cpuset_and(&tmp_mask, spdk_thread_get_cpumask(thread));
     200           0 :                 spdk_json_write_named_string(ctx->w, "cpumask", spdk_cpuset_fmt(&tmp_mask));
     201           0 :                 spdk_json_write_named_uint64(ctx->w, "busy", stats.busy_tsc);
     202           0 :                 spdk_json_write_named_uint64(ctx->w, "idle", stats.idle_tsc);
     203           0 :                 spdk_json_write_named_uint64(ctx->w, "active_pollers_count", active_pollers_count);
     204           0 :                 spdk_json_write_named_uint64(ctx->w, "timed_pollers_count", timed_pollers_count);
     205           0 :                 spdk_json_write_named_uint64(ctx->w, "paused_pollers_count", paused_pollers_count);
     206           0 :                 spdk_json_write_object_end(ctx->w);
     207             :         }
     208           0 : }
     209             : 
     210             : static void
     211           0 : rpc_thread_get_stats(struct spdk_jsonrpc_request *request,
     212             :                      const struct spdk_json_val *params)
     213             : {
     214           0 :         if (params) {
     215           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     216             :                                                  "'thread_get_stats' requires no arguments");
     217           0 :                 return;
     218             :         }
     219             : 
     220           0 :         rpc_thread_get_stats_for_each(request, _rpc_thread_get_stats);
     221             : }
     222             : 
     223           0 : SPDK_RPC_REGISTER("thread_get_stats", rpc_thread_get_stats, SPDK_RPC_RUNTIME)
     224             : 
     225             : static void
     226           0 : rpc_get_poller(struct spdk_poller *poller, struct spdk_json_write_ctx *w)
     227             : {
     228           0 :         struct spdk_poller_stats stats;
     229             :         uint64_t period_ticks;
     230             : 
     231           0 :         period_ticks = spdk_poller_get_period_ticks(poller);
     232           0 :         spdk_poller_get_stats(poller, &stats);
     233             : 
     234           0 :         spdk_json_write_object_begin(w);
     235           0 :         spdk_json_write_named_string(w, "name", spdk_poller_get_name(poller));
     236           0 :         spdk_json_write_named_uint64(w, "id", spdk_poller_get_id(poller));
     237           0 :         spdk_json_write_named_string(w, "state", spdk_poller_get_state_str(poller));
     238           0 :         spdk_json_write_named_uint64(w, "run_count", stats.run_count);
     239           0 :         spdk_json_write_named_uint64(w, "busy_count", stats.busy_count);
     240           0 :         if (period_ticks) {
     241           0 :                 spdk_json_write_named_uint64(w, "period_ticks", period_ticks);
     242             :         }
     243           0 :         spdk_json_write_object_end(w);
     244           0 : }
     245             : 
     246             : static void
     247           0 : _rpc_thread_get_pollers(void *arg)
     248             : {
     249           0 :         struct rpc_get_stats_ctx *ctx = arg;
     250           0 :         struct spdk_thread *thread = spdk_get_thread();
     251             :         struct spdk_poller *poller;
     252             : 
     253           0 :         spdk_json_write_object_begin(ctx->w);
     254           0 :         spdk_json_write_named_string(ctx->w, "name", spdk_thread_get_name(thread));
     255           0 :         spdk_json_write_named_uint64(ctx->w, "id", spdk_thread_get_id(thread));
     256             : 
     257           0 :         spdk_json_write_named_array_begin(ctx->w, "active_pollers");
     258           0 :         for (poller = spdk_thread_get_first_active_poller(thread); poller != NULL;
     259           0 :              poller = spdk_thread_get_next_active_poller(poller)) {
     260           0 :                 rpc_get_poller(poller, ctx->w);
     261             :         }
     262           0 :         spdk_json_write_array_end(ctx->w);
     263             : 
     264           0 :         spdk_json_write_named_array_begin(ctx->w, "timed_pollers");
     265           0 :         for (poller = spdk_thread_get_first_timed_poller(thread); poller != NULL;
     266           0 :              poller = spdk_thread_get_next_timed_poller(poller)) {
     267           0 :                 rpc_get_poller(poller, ctx->w);
     268             :         }
     269           0 :         spdk_json_write_array_end(ctx->w);
     270             : 
     271           0 :         spdk_json_write_named_array_begin(ctx->w, "paused_pollers");
     272           0 :         for (poller = spdk_thread_get_first_paused_poller(thread); poller != NULL;
     273           0 :              poller = spdk_thread_get_next_paused_poller(poller)) {
     274           0 :                 rpc_get_poller(poller, ctx->w);
     275             :         }
     276           0 :         spdk_json_write_array_end(ctx->w);
     277             : 
     278           0 :         spdk_json_write_object_end(ctx->w);
     279           0 : }
     280             : 
     281             : static void
     282           0 : rpc_thread_get_pollers(struct spdk_jsonrpc_request *request,
     283             :                        const struct spdk_json_val *params)
     284             : {
     285           0 :         if (params) {
     286           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     287             :                                                  "'thread_get_pollers' requires no arguments");
     288           0 :                 return;
     289             :         }
     290             : 
     291           0 :         rpc_thread_get_stats_for_each(request, _rpc_thread_get_pollers);
     292             : }
     293             : 
     294           0 : SPDK_RPC_REGISTER("thread_get_pollers", rpc_thread_get_pollers, SPDK_RPC_RUNTIME)
     295             : 
     296             : static void
     297           0 : rpc_get_io_channel(struct spdk_io_channel *ch, struct spdk_json_write_ctx *w)
     298             : {
     299           0 :         spdk_json_write_object_begin(w);
     300           0 :         spdk_json_write_named_string(w, "name", spdk_io_channel_get_io_device_name(ch));
     301           0 :         spdk_json_write_named_uint32(w, "ref", spdk_io_channel_get_ref_count(ch));
     302           0 :         spdk_json_write_object_end(w);
     303           0 : }
     304             : 
     305             : static void
     306           0 : _rpc_thread_get_io_channels(void *arg)
     307             : {
     308           0 :         struct rpc_get_stats_ctx *ctx = arg;
     309           0 :         struct spdk_thread *thread = spdk_get_thread();
     310             :         struct spdk_io_channel *ch;
     311             : 
     312           0 :         spdk_json_write_object_begin(ctx->w);
     313           0 :         spdk_json_write_named_string(ctx->w, "name", spdk_thread_get_name(thread));
     314             : 
     315           0 :         spdk_json_write_named_array_begin(ctx->w, "io_channels");
     316           0 :         for (ch = spdk_thread_get_first_io_channel(thread); ch != NULL;
     317           0 :              ch = spdk_thread_get_next_io_channel(ch)) {
     318           0 :                 rpc_get_io_channel(ch, ctx->w);
     319             :         }
     320           0 :         spdk_json_write_array_end(ctx->w);
     321             : 
     322           0 :         spdk_json_write_object_end(ctx->w);
     323           0 : }
     324             : 
     325             : static void
     326           0 : rpc_thread_get_io_channels(struct spdk_jsonrpc_request *request,
     327             :                            const struct spdk_json_val *params)
     328             : {
     329           0 :         if (params) {
     330           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     331             :                                                  "'thread_get_io_channels' requires no arguments");
     332           0 :                 return;
     333             :         }
     334             : 
     335           0 :         rpc_thread_get_stats_for_each(request, _rpc_thread_get_io_channels);
     336             : }
     337             : 
     338           0 : SPDK_RPC_REGISTER("thread_get_io_channels", rpc_thread_get_io_channels, SPDK_RPC_RUNTIME);
     339             : 
     340             : static void
     341           0 : rpc_framework_get_reactors_done(void *arg1, void *arg2)
     342             : {
     343           0 :         struct rpc_get_stats_ctx *ctx = arg1;
     344             : 
     345           0 :         spdk_json_write_array_end(ctx->w);
     346           0 :         spdk_json_write_object_end(ctx->w);
     347           0 :         spdk_jsonrpc_end_result(ctx->request, ctx->w);
     348             : 
     349           0 :         free(ctx);
     350           0 : }
     351             : 
     352             : #define GET_DELTA(end, start)   (end >= start ? end - start : 0)
     353             : 
     354             : static void
     355           0 : _rpc_framework_get_reactors(void *arg1, void *arg2)
     356             : {
     357           0 :         struct rpc_get_stats_ctx *ctx = arg1;
     358             :         uint32_t current_core;
     359             :         uint32_t curr_core_freq;
     360           0 :         uint64_t sys, usr, irq;
     361             :         struct spdk_reactor *reactor;
     362             :         struct spdk_lw_thread *lw_thread;
     363             :         struct spdk_thread *thread;
     364           0 :         struct spdk_cpuset tmp_mask = {};
     365             :         struct spdk_governor *governor;
     366             : 
     367           0 :         current_core = spdk_env_get_current_core();
     368           0 :         reactor = spdk_reactor_get(current_core);
     369             : 
     370           0 :         assert(reactor != NULL);
     371             : 
     372           0 :         spdk_json_write_object_begin(ctx->w);
     373           0 :         spdk_json_write_named_uint32(ctx->w, "lcore", current_core);
     374           0 :         spdk_json_write_named_uint64(ctx->w, "tid", spdk_get_tid());
     375           0 :         spdk_json_write_named_uint64(ctx->w, "busy", reactor->busy_tsc);
     376           0 :         spdk_json_write_named_uint64(ctx->w, "idle", reactor->idle_tsc);
     377           0 :         spdk_json_write_named_bool(ctx->w, "in_interrupt", reactor->in_interrupt);
     378             : 
     379           0 :         if (app_get_proc_stat(current_core, &usr, &sys, &irq) != 0) {
     380           0 :                 irq = sys = usr = 0;
     381             :         }
     382           0 :         spdk_json_write_named_uint64(ctx->w, "irq", irq);
     383           0 :         spdk_json_write_named_uint64(ctx->w, "sys", sys);
     384           0 :         spdk_json_write_named_uint64(ctx->w, "usr", usr);
     385             : 
     386           0 :         governor = spdk_governor_get();
     387           0 :         if (governor != NULL) {
     388             :                 /* Governor returns core freqs in kHz, we want MHz. */
     389           0 :                 curr_core_freq = governor->get_core_curr_freq(current_core) / 1000;
     390           0 :                 spdk_json_write_named_uint32(ctx->w, "core_freq", curr_core_freq);
     391             :         }
     392             : 
     393           0 :         spdk_json_write_named_array_begin(ctx->w, "lw_threads");
     394           0 :         TAILQ_FOREACH(lw_thread, &reactor->threads, link) {
     395           0 :                 thread = spdk_thread_get_from_ctx(lw_thread);
     396             : 
     397           0 :                 spdk_json_write_object_begin(ctx->w);
     398           0 :                 spdk_json_write_named_string(ctx->w, "name", spdk_thread_get_name(thread));
     399           0 :                 spdk_json_write_named_uint64(ctx->w, "id", spdk_thread_get_id(thread));
     400           0 :                 spdk_cpuset_copy(&tmp_mask, spdk_app_get_core_mask());
     401           0 :                 spdk_cpuset_and(&tmp_mask, spdk_thread_get_cpumask(thread));
     402           0 :                 spdk_json_write_named_string(ctx->w, "cpumask", spdk_cpuset_fmt(&tmp_mask));
     403           0 :                 spdk_json_write_named_uint64(ctx->w, "elapsed",
     404           0 :                                              GET_DELTA(ctx->now, lw_thread->tsc_start));
     405           0 :                 spdk_json_write_object_end(ctx->w);
     406             :         }
     407           0 :         spdk_json_write_array_end(ctx->w);
     408             : 
     409           0 :         spdk_json_write_object_end(ctx->w);
     410           0 : }
     411             : 
     412             : static void
     413           0 : rpc_framework_get_reactors(struct spdk_jsonrpc_request *request,
     414             :                            const struct spdk_json_val *params)
     415             : {
     416             :         struct rpc_get_stats_ctx *ctx;
     417             : 
     418           0 :         if (params) {
     419           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     420             :                                                  "`framework_get_reactors` requires no arguments");
     421           0 :                 return;
     422             :         }
     423             : 
     424           0 :         ctx = calloc(1, sizeof(*ctx));
     425           0 :         if (!ctx) {
     426           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
     427             :                                                  "Memory allocation error");
     428           0 :                 return;
     429             :         }
     430             : 
     431           0 :         ctx->now = spdk_get_ticks();
     432           0 :         ctx->request = request;
     433           0 :         ctx->w = spdk_jsonrpc_begin_result(ctx->request);
     434             : 
     435           0 :         spdk_json_write_object_begin(ctx->w);
     436           0 :         spdk_json_write_named_uint64(ctx->w, "tick_rate", spdk_get_ticks_hz());
     437           0 :         spdk_json_write_named_uint64(ctx->w, "pid", getpid());
     438           0 :         spdk_json_write_named_array_begin(ctx->w, "reactors");
     439             : 
     440           0 :         spdk_for_each_reactor(_rpc_framework_get_reactors, ctx, NULL,
     441             :                               rpc_framework_get_reactors_done);
     442             : }
     443             : 
     444           0 : SPDK_RPC_REGISTER("framework_get_reactors", rpc_framework_get_reactors, SPDK_RPC_RUNTIME)
     445             : 
     446             : struct rpc_set_scheduler_ctx {
     447             :         char *name;
     448             :         uint64_t period;
     449             : };
     450             : 
     451             : static void
     452           0 : free_rpc_framework_set_scheduler(struct rpc_set_scheduler_ctx *r)
     453             : {
     454           0 :         free(r->name);
     455           0 : }
     456             : 
     457             : static const struct spdk_json_object_decoder rpc_set_scheduler_decoders[] = {
     458             :         {"name", offsetof(struct rpc_set_scheduler_ctx, name), spdk_json_decode_string},
     459             :         {"period", offsetof(struct rpc_set_scheduler_ctx, period), spdk_json_decode_uint64, true},
     460             : };
     461             : 
     462             : static void
     463           0 : rpc_framework_set_scheduler(struct spdk_jsonrpc_request *request,
     464             :                             const struct spdk_json_val *params)
     465             : {
     466           0 :         struct rpc_set_scheduler_ctx req = {NULL};
     467           0 :         struct spdk_scheduler *scheduler = NULL;
     468             :         int ret;
     469             : 
     470           0 :         ret = spdk_json_decode_object_relaxed(params, rpc_set_scheduler_decoders,
     471             :                                               SPDK_COUNTOF(rpc_set_scheduler_decoders),
     472             :                                               &req);
     473           0 :         if (ret) {
     474           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     475             :                                                  "Invalid parameters");
     476           0 :                 goto end;
     477             :         }
     478             : 
     479           0 :         scheduler = spdk_scheduler_get();
     480             :         /* SPDK does not support changing scheduler back to static. */
     481           0 :         if (scheduler != NULL && (strcmp(req.name, "static") == 0) &&
     482           0 :             strcmp(scheduler->name, "static") != 0) {
     483           0 :                 spdk_jsonrpc_send_error_response(request,
     484             :                                                  SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     485             :                                                  "Static scheduler cannot be re-enabled "
     486             :                                                  "after a different scheduler was selected");
     487           0 :                 goto end;
     488             :         }
     489             : 
     490           0 :         if (req.period != 0) {
     491           0 :                 spdk_scheduler_set_period(req.period);
     492           0 :         } else if (spdk_scheduler_get_period() == 0) {
     493             :                 /* User didn't specify a period, and no period has been set
     494             :                  * previously, so set it now to 1 second.
     495             :                  */
     496           0 :                 spdk_scheduler_set_period(SPDK_SEC_TO_USEC);
     497             :         }
     498             : 
     499           0 :         ret = spdk_scheduler_set(req.name);
     500           0 :         if (ret) {
     501           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
     502             :                                                  spdk_strerror(ret));
     503           0 :                 goto end;
     504             :         }
     505             : 
     506           0 :         scheduler = spdk_scheduler_get();
     507           0 :         if (scheduler != NULL && scheduler->set_opts != NULL) {
     508           0 :                 ret = scheduler->set_opts(params);
     509             :         }
     510           0 :         if (ret) {
     511           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, spdk_strerror(ret));
     512           0 :                 goto end;
     513             :         }
     514             : 
     515           0 :         spdk_jsonrpc_send_bool_response(request, true);
     516             : 
     517           0 : end:
     518           0 :         free_rpc_framework_set_scheduler(&req);
     519           0 : }
     520           0 : SPDK_RPC_REGISTER("framework_set_scheduler", rpc_framework_set_scheduler,
     521             :                   SPDK_RPC_STARTUP | SPDK_RPC_RUNTIME)
     522             : 
     523             : static void
     524           0 : rpc_framework_get_scheduler(struct spdk_jsonrpc_request *request,
     525             :                             const struct spdk_json_val *params)
     526             : {
     527             :         struct spdk_json_write_ctx *w;
     528           0 :         struct spdk_scheduler *scheduler = spdk_scheduler_get();
     529           0 :         uint64_t scheduler_period = spdk_scheduler_get_period();
     530           0 :         struct spdk_governor *governor = spdk_governor_get();
     531             : 
     532           0 :         if (params) {
     533           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     534             :                                                  "'rpc_get_scheduler' requires no arguments");
     535           0 :                 return;
     536             :         }
     537             : 
     538           0 :         w = spdk_jsonrpc_begin_result(request);
     539           0 :         spdk_json_write_object_begin(w);
     540           0 :         if (scheduler) {
     541           0 :                 spdk_json_write_named_string(w, "scheduler_name", scheduler->name);
     542             :         }
     543           0 :         spdk_json_write_named_uint64(w, "scheduler_period", scheduler_period);
     544           0 :         if (governor != NULL) {
     545           0 :                 spdk_json_write_named_string(w, "governor_name", governor->name);
     546             :         }
     547             : 
     548           0 :         if (scheduler != NULL && scheduler->get_opts != NULL) {
     549           0 :                 scheduler->get_opts(w);
     550             :         }
     551             : 
     552           0 :         spdk_json_write_object_end(w);
     553           0 :         spdk_jsonrpc_end_result(request, w);
     554             : }
     555           0 : SPDK_RPC_REGISTER("framework_get_scheduler", rpc_framework_get_scheduler, SPDK_RPC_RUNTIME)
     556             : 
     557             : static void
     558           0 : rpc_framework_get_governor(struct spdk_jsonrpc_request *request,
     559             :                            const struct spdk_json_val *params)
     560             : {
     561             :         struct spdk_json_write_ctx *w;
     562           0 :         struct spdk_governor *governor = spdk_governor_get();
     563             : 
     564           0 :         if (params) {
     565           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     566             :                                                  "'rpc_get_governor' requires no arguments");
     567           0 :                 return;
     568             :         }
     569             : 
     570           0 :         w = spdk_jsonrpc_begin_result(request);
     571           0 :         spdk_json_write_object_begin(w);
     572             : 
     573           0 :         if (governor != NULL) {
     574             :                 uint32_t core, index, num;
     575           0 :                 uint32_t freqs[SPDK_MAX_LCORE_FREQS];
     576             : 
     577           0 :                 spdk_json_write_named_string(w, "governor_name", governor->name);
     578             : 
     579           0 :                 spdk_json_write_named_object_begin(w, "module_specific");
     580             : 
     581           0 :                 governor->dump_info_json(w);
     582             : 
     583           0 :                 spdk_json_write_object_end(w);
     584             : 
     585           0 :                 spdk_json_write_named_array_begin(w, "cores");
     586             : 
     587           0 :                 SPDK_ENV_FOREACH_CORE(core) {
     588           0 :                         spdk_json_write_object_begin(w);
     589           0 :                         spdk_json_write_named_uint32(w, "lcore_id", core);
     590             : 
     591           0 :                         memset(freqs, 0, SPDK_MAX_LCORE_FREQS * sizeof(uint32_t));
     592             : 
     593           0 :                         num = governor->get_core_avail_freqs(core, freqs, SPDK_MAX_LCORE_FREQS);
     594             : 
     595           0 :                         spdk_json_write_named_array_begin(w, "available_frequencies");
     596           0 :                         for (index = 0; index < num; index++) {
     597           0 :                                 spdk_json_write_uint32(w, freqs[index]);
     598             :                         }
     599           0 :                         spdk_json_write_array_end(w);
     600             : 
     601           0 :                         spdk_json_write_named_uint32(w, "current_frequency", governor->get_core_curr_freq(core));
     602           0 :                         spdk_json_write_object_end(w);
     603             :                 }
     604             : 
     605           0 :                 spdk_json_write_array_end(w);
     606             :         }
     607             : 
     608           0 :         spdk_json_write_object_end(w);
     609           0 :         spdk_jsonrpc_end_result(request, w);
     610             : }
     611           0 : SPDK_RPC_REGISTER("framework_get_governor", rpc_framework_get_governor, SPDK_RPC_RUNTIME)
     612             : 
     613             : struct rpc_thread_set_cpumask_ctx {
     614             :         struct spdk_jsonrpc_request *request;
     615             :         struct spdk_cpuset cpumask;
     616             :         int status;
     617             :         struct spdk_thread *orig_thread;
     618             : };
     619             : 
     620             : static void
     621           0 : rpc_thread_set_cpumask_done(void *_ctx)
     622             : {
     623           0 :         struct rpc_thread_set_cpumask_ctx *ctx = _ctx;
     624             : 
     625           0 :         if (ctx->status == 0) {
     626           0 :                 spdk_jsonrpc_send_bool_response(ctx->request, true);
     627             :         } else {
     628           0 :                 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
     629           0 :                                                  spdk_strerror(-ctx->status));
     630             :         }
     631             : 
     632           0 :         free(ctx);
     633           0 : }
     634             : 
     635             : static void
     636           0 : _rpc_thread_set_cpumask(void *_ctx)
     637             : {
     638           0 :         struct rpc_thread_set_cpumask_ctx *ctx = _ctx;
     639             : 
     640           0 :         ctx->status = spdk_thread_set_cpumask(&ctx->cpumask);
     641             : 
     642           0 :         spdk_thread_send_msg(ctx->orig_thread, rpc_thread_set_cpumask_done, ctx);
     643           0 : }
     644             : 
     645             : struct rpc_thread_set_cpumask {
     646             :         uint64_t id;
     647             :         char *cpumask;
     648             : };
     649             : 
     650             : static const struct spdk_json_object_decoder rpc_thread_set_cpumask_decoders[] = {
     651             :         {"id", offsetof(struct rpc_thread_set_cpumask, id), spdk_json_decode_uint64},
     652             :         {"cpumask", offsetof(struct rpc_thread_set_cpumask, cpumask), spdk_json_decode_string},
     653             : };
     654             : 
     655             : static void
     656           0 : rpc_thread_set_cpumask(struct spdk_jsonrpc_request *request,
     657             :                        const struct spdk_json_val *params)
     658             : {
     659           0 :         struct rpc_thread_set_cpumask req = {};
     660             :         struct rpc_thread_set_cpumask_ctx *ctx;
     661             :         const struct spdk_cpuset *coremask;
     662           0 :         struct spdk_cpuset tmp_mask;
     663             :         struct spdk_thread *thread;
     664             :         int rc;
     665             : 
     666           0 :         ctx = calloc(1, sizeof(*ctx));
     667           0 :         if (ctx == NULL) {
     668           0 :                 SPDK_ERRLOG("Memory allocation failed\n");
     669           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
     670             :                                                  "Memory allocation failed");
     671           0 :                 return;
     672             :         }
     673             : 
     674           0 :         if (spdk_json_decode_object(params, rpc_thread_set_cpumask_decoders,
     675             :                                     SPDK_COUNTOF(rpc_thread_set_cpumask_decoders),
     676             :                                     &req)) {
     677           0 :                 SPDK_ERRLOG("spdk_json_decode_object failed\n");
     678           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     679             :                                                  "spdk_json_decode_object failed");
     680           0 :                 goto err;
     681             :         }
     682             : 
     683           0 :         thread = spdk_thread_get_by_id(req.id);
     684           0 :         if (thread == NULL) {
     685           0 :                 SPDK_ERRLOG("Thread %" PRIu64 " does not exist\n", req.id);
     686           0 :                 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     687             :                                                      "Thread %" PRIu64 " does not exist", req.id);
     688           0 :                 goto err;
     689             :         }
     690             : 
     691           0 :         rc = spdk_app_parse_core_mask(req.cpumask, &ctx->cpumask);
     692           0 :         if (rc != 0) {
     693           0 :                 SPDK_ERRLOG("Invalid cpumask %s\n", req.cpumask);
     694           0 :                 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
     695             :                                                      "Invalid cpumask %s", req.cpumask);
     696           0 :                 goto err;
     697             :         }
     698             : 
     699           0 :         if (spdk_cpuset_count(&ctx->cpumask) == 0) {
     700           0 :                 coremask = spdk_app_get_core_mask();
     701           0 :                 spdk_cpuset_copy(&tmp_mask, coremask);
     702           0 :                 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
     703             :                                                      "No CPU is selected from reactor mask %s\n",
     704             :                                                      spdk_cpuset_fmt(&tmp_mask));
     705           0 :                 goto err;
     706             :         }
     707             : 
     708             :         /* There may be any reactors running in interrupt mode. But currently,
     709             :          * when interrupt ability of the spdk_thread is not enabled,
     710             :          * spdk_thread can't get executed on reactor which runs in interrupt.
     711             :          * Exclude the situation that reactors specified by the cpumask are
     712             :          * all in interrupt mode.
     713             :          */
     714           0 :         if (!spdk_interrupt_mode_is_enabled()) {
     715           0 :                 struct spdk_reactor *local_reactor = spdk_reactor_get(spdk_env_get_current_core());
     716           0 :                 struct spdk_cpuset tmp_cpuset;
     717             : 
     718             :                 /* Masking off reactors which are in interrupt mode */
     719           0 :                 spdk_cpuset_copy(&tmp_cpuset, &local_reactor->notify_cpuset);
     720           0 :                 spdk_cpuset_negate(&tmp_cpuset);
     721           0 :                 spdk_cpuset_and(&tmp_cpuset, &ctx->cpumask);
     722           0 :                 if (spdk_cpuset_count(&tmp_cpuset) == 0) {
     723           0 :                         spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
     724             :                                                              "cpumask %s are all in interrupt mode, and can't be scheduled yet\n",
     725             :                                                              req.cpumask);
     726           0 :                         goto err;
     727             :                 }
     728             :         }
     729             : 
     730           0 :         ctx->request = request;
     731           0 :         ctx->orig_thread = spdk_get_thread();
     732             : 
     733           0 :         spdk_thread_send_msg(thread, _rpc_thread_set_cpumask, ctx);
     734             : 
     735           0 :         free(req.cpumask);
     736           0 :         return;
     737             : 
     738           0 : err:
     739           0 :         free(req.cpumask);
     740           0 :         free(ctx);
     741             : }
     742           0 : SPDK_RPC_REGISTER("thread_set_cpumask", rpc_thread_set_cpumask, SPDK_RPC_RUNTIME)
     743           0 : SPDK_LOG_REGISTER_COMPONENT(app_rpc)

Generated by: LCOV version 1.15