LCOV - code coverage report
Current view: top level - lib/event - scheduler_static.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 1 73 1.4 %
Date: 2024-12-07 19:14:38 Functions: 1 5 20.0 %

          Line data    Source code
       1             : /*   SPDX-License-Identifier: BSD-3-Clause
       2             :  *   Copyright (C) 2020 Intel Corporation.
       3             :  *   Copyright (C) 2024 Samsung Electronics Co., Ltd.
       4             :  *   All rights reserved.
       5             :  */
       6             : 
       7             : #include "spdk/stdinc.h"
       8             : #include "spdk/likely.h"
       9             : #include "spdk/event.h"
      10             : #include "spdk/log.h"
      11             : #include "spdk/env.h"
      12             : #include "spdk/string.h"
      13             : #include "spdk/scheduler.h"
      14             : 
      15             : #include "spdk_internal/event.h"
      16             : #include "event_internal.h"
      17             : 
      18             : static bool g_first_load = true;
      19             : 
      20             : static int
      21           0 : init_static(void)
      22             : {
      23           0 :         if (g_first_load) {
      24             :                 /* There is no scheduling performed by static scheduler,
      25             :                  * do not set the scheduling period. */
      26           0 :                 spdk_scheduler_set_period(0);
      27             :         } else {
      28             :                 /* Schedule a balance to happen immediately, so that
      29             :                  * we can reset each thread's lcore back to its original
      30             :                  * state.
      31             :                  */
      32           0 :                 spdk_scheduler_set_period(1);
      33             :         }
      34             : 
      35           0 :         return 0;
      36             : }
      37             : 
      38             : static void
      39           0 : deinit_static(void)
      40             : {
      41           0 :         g_first_load = false;
      42           0 : }
      43             : 
      44             : static void
      45           0 : balance_static(struct spdk_scheduler_core_info *cores, uint32_t core_count)
      46             : {
      47             :         struct spdk_scheduler_core_info *core_info;
      48             :         struct spdk_scheduler_thread_info *thread_info;
      49             :         struct spdk_lw_thread *lw_thread;
      50             :         struct spdk_thread *thread;
      51             :         uint32_t i, j;
      52             : 
      53           0 :         for (i = 0; i < core_count; i++) {
      54           0 :                 core_info = &cores[i];
      55           0 :                 core_info->interrupt_mode = false;
      56           0 :                 for (j = 0; j < core_info->threads_count; j++) {
      57           0 :                         thread_info = &core_info->thread_infos[j];
      58           0 :                         thread = spdk_thread_get_by_id(thread_info->thread_id);
      59           0 :                         lw_thread = spdk_thread_get_ctx(thread);
      60           0 :                         thread_info->lcore = lw_thread->initial_lcore;
      61             :                 }
      62             :         }
      63             : 
      64             :         /* We've restored the original state now, so we don't need to
      65             :          * balance() anymore.
      66             :          */
      67           0 :         spdk_scheduler_set_period(0);
      68           0 : }
      69             : 
      70             : static const struct spdk_json_object_decoder static_sched_decoders[] = {
      71             :         {"mappings", 0, spdk_json_decode_string, true},
      72             : };
      73             : 
      74             : static int
      75           0 : set_opts_static(const struct spdk_json_val *opts)
      76             : {
      77           0 :         char *tok, *mappings = NULL, *copy, *sp = NULL;
      78             :         bool valid;
      79             : 
      80           0 :         if (opts != NULL) {
      81           0 :                 if (spdk_json_decode_object_relaxed(opts, static_sched_decoders,
      82             :                                                     SPDK_COUNTOF(static_sched_decoders),
      83             :                                                     &mappings)) {
      84           0 :                         SPDK_ERRLOG("Decoding scheduler opts JSON failed\n");
      85           0 :                         return -EINVAL;
      86             :                 }
      87             :         }
      88             : 
      89           0 :         if (mappings == NULL) {
      90           0 :                 return 0;
      91             :         }
      92             : 
      93           0 :         copy = strdup(mappings);
      94           0 :         if (copy == NULL) {
      95           0 :                 free(mappings);
      96           0 :                 return -ENOMEM;
      97             :         }
      98             : 
      99           0 :         valid = true;
     100           0 :         tok = strtok_r(mappings, ":", &sp);
     101           0 :         while (tok) {
     102           0 :                 struct spdk_lw_thread *lw_thread = NULL;
     103             :                 struct spdk_thread *thread;
     104             :                 int thread_id, core;
     105             : 
     106           0 :                 thread_id = spdk_strtol(tok, 10);
     107           0 :                 if (thread_id > 0) {
     108           0 :                         thread = spdk_thread_get_by_id(thread_id);
     109           0 :                         if (thread != NULL) {
     110           0 :                                 lw_thread = spdk_thread_get_ctx(thread);
     111             :                         }
     112             :                 }
     113           0 :                 if (lw_thread == NULL) {
     114           0 :                         SPDK_ERRLOG("invalid thread ID '%s' in mappings '%s'\n", tok, copy);
     115           0 :                         valid = false;
     116           0 :                         break;
     117             :                 }
     118             : 
     119           0 :                 tok = strtok_r(NULL, ",", &sp);
     120           0 :                 core = spdk_strtol(tok, 10);
     121           0 :                 if (core < 0 || spdk_reactor_get(core) == NULL) {
     122           0 :                         SPDK_ERRLOG("invalid core number '%s' in mappings '%s'\n", tok, copy);
     123           0 :                         valid = false;
     124           0 :                         break;
     125             :                 }
     126             : 
     127           0 :                 if (!spdk_cpuset_get_cpu(spdk_thread_get_cpumask(thread), core)) {
     128           0 :                         SPDK_ERRLOG("core %d not in thread %d cpumask\n", core, thread_id);
     129           0 :                         valid = false;
     130           0 :                         break;
     131             :                 }
     132             : 
     133           0 :                 tok = strtok_r(NULL, ":", &sp);
     134             :         }
     135           0 :         free(mappings);
     136           0 :         if (!valid) {
     137           0 :                 free(copy);
     138           0 :                 return -EINVAL;
     139             :         }
     140             : 
     141           0 :         tok = strtok_r(copy, ":", &sp);
     142           0 :         while (tok) {
     143           0 :                 struct spdk_lw_thread *lw_thread = NULL;
     144             :                 struct spdk_thread *thread;
     145             :                 int thread_id, core;
     146             : 
     147           0 :                 thread_id = spdk_strtol(tok, 10);
     148           0 :                 thread = spdk_thread_get_by_id(thread_id);
     149           0 :                 lw_thread = spdk_thread_get_ctx(thread);
     150           0 :                 tok = strtok_r(NULL, ",", &sp);
     151           0 :                 core = spdk_strtol(tok, 10);
     152             :                 /* initial_lcore saves the static scheduler's lcore mapping.
     153             :                  * This is used to restore the previous mapping if we
     154             :                  * change to another scheduler and then back. So we can just
     155             :                  * change the ->initial_lcore here and kick the scheduler to
     156             :                  * put the new mapping into effect.
     157             :                  */
     158           0 :                 lw_thread->initial_lcore = core;
     159           0 :                 tok = strtok_r(NULL, ":", &sp);
     160             :         }
     161           0 :         free(copy);
     162             : 
     163             :         /* We have updated some core placements, so kick the scheduler to
     164             :          * apply those new placements.
     165             :          */
     166           0 :         spdk_scheduler_set_period(1);
     167           0 :         return 0;
     168             : }
     169             : 
     170             : static struct spdk_scheduler scheduler = {
     171             :         .name = "static",
     172             :         .init = init_static,
     173             :         .deinit = deinit_static,
     174             :         .balance = balance_static,
     175             :         .set_opts = set_opts_static,
     176             : };
     177           1 : SPDK_SCHEDULER_REGISTER(scheduler);

Generated by: LCOV version 1.15