LCOV - code coverage report
Current view: top level - spdk/lib/init - subsystem.c (source / functions) Hit Total Coverage
Test: Combined Lines: 96 105 91.4 %
Date: 2024-07-11 17:06:07 Functions: 15 16 93.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 62 80 77.5 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2016 Intel Corporation.
       3                 :            :  *   All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include "spdk/stdinc.h"
       7                 :            : 
       8                 :            : #include "spdk/init.h"
       9                 :            : #include "spdk/log.h"
      10                 :            : #include "spdk/queue.h"
      11                 :            : #include "spdk/thread.h"
      12                 :            : 
      13                 :            : #include "spdk_internal/init.h"
      14                 :            : #include "spdk/env.h"
      15                 :            : 
      16                 :            : #include "spdk/json.h"
      17                 :            : 
      18                 :            : #include "subsystem.h"
      19                 :            : 
      20                 :            : TAILQ_HEAD(spdk_subsystem_list, spdk_subsystem);
      21                 :            : struct spdk_subsystem_list g_subsystems = TAILQ_HEAD_INITIALIZER(g_subsystems);
      22                 :            : 
      23                 :            : TAILQ_HEAD(spdk_subsystem_depend_list, spdk_subsystem_depend);
      24                 :            : struct spdk_subsystem_depend_list g_subsystems_deps = TAILQ_HEAD_INITIALIZER(g_subsystems_deps);
      25                 :            : static struct spdk_subsystem *g_next_subsystem;
      26                 :            : static bool g_subsystems_initialized = false;
      27                 :            : static bool g_subsystems_init_interrupted = false;
      28                 :            : static spdk_subsystem_init_fn g_subsystem_start_fn = NULL;
      29                 :            : static void *g_subsystem_start_arg = NULL;
      30                 :            : static spdk_msg_fn g_subsystem_stop_fn = NULL;
      31                 :            : static void *g_subsystem_stop_arg = NULL;
      32                 :            : static struct spdk_thread *g_fini_thread = NULL;
      33                 :            : 
      34                 :            : void
      35                 :      22783 : spdk_add_subsystem(struct spdk_subsystem *subsystem)
      36                 :            : {
      37                 :      22783 :         TAILQ_INSERT_TAIL(&g_subsystems, subsystem, tailq);
      38                 :      22783 : }
      39                 :            : 
      40                 :            : void
      41                 :      23710 : spdk_add_subsystem_depend(struct spdk_subsystem_depend *depend)
      42                 :            : {
      43                 :      23710 :         TAILQ_INSERT_TAIL(&g_subsystems_deps, depend, tailq);
      44                 :      23710 : }
      45                 :            : 
      46                 :            : static struct spdk_subsystem *
      47                 :      73852 : _subsystem_find(struct spdk_subsystem_list *list, const char *name)
      48                 :            : {
      49                 :            :         struct spdk_subsystem *iter;
      50                 :            : 
      51         [ +  + ]:     355621 :         TAILQ_FOREACH(iter, list, tailq) {
      52   [ +  +  -  +  :     349560 :                 if (strcmp(name, iter->name) == 0) {
                   +  + ]
      53                 :      67791 :                         return iter;
      54                 :            :                 }
      55                 :            :         }
      56                 :            : 
      57                 :       6061 :         return NULL;
      58                 :            : }
      59                 :            : 
      60                 :            : struct spdk_subsystem *
      61                 :      45780 : subsystem_find(const char *name)
      62                 :            : {
      63                 :      45780 :         return _subsystem_find(&g_subsystems, name);
      64                 :            : }
      65                 :            : 
      66                 :            : bool
      67                 :          0 : spdk_subsystem_exists(const char *name)
      68                 :            : {
      69                 :          0 :         return subsystem_find(name) != NULL;
      70                 :            : }
      71                 :            : 
      72                 :            : struct spdk_subsystem *
      73                 :       1336 : subsystem_get_first(void)
      74                 :            : {
      75                 :       1336 :         return TAILQ_FIRST(&g_subsystems);
      76                 :            : }
      77                 :            : 
      78                 :            : struct spdk_subsystem *
      79                 :      13961 : subsystem_get_next(struct spdk_subsystem *cur_subsystem)
      80                 :            : {
      81                 :      13961 :         return TAILQ_NEXT(cur_subsystem, tailq);
      82                 :            : }
      83                 :            : 
      84                 :            : 
      85                 :            : struct spdk_subsystem_depend *
      86                 :      13961 : subsystem_get_first_depend(void)
      87                 :            : {
      88                 :      13961 :         return TAILQ_FIRST(&g_subsystems_deps);
      89                 :            : }
      90                 :            : 
      91                 :            : struct spdk_subsystem_depend *
      92                 :     158902 : subsystem_get_next_depend(struct spdk_subsystem_depend *cur_depend)
      93                 :            : {
      94                 :     158902 :         return TAILQ_NEXT(cur_depend, tailq);
      95                 :            : }
      96                 :            : 
      97                 :            : static void
      98                 :       2899 : subsystem_sort(void)
      99                 :            : {
     100                 :            :         bool has_dependency, all_dependencies_met;
     101                 :            :         struct spdk_subsystem *subsystem, *subsystem_tmp;
     102                 :            :         struct spdk_subsystem_depend *subsystem_dep;
     103                 :       1398 :         struct spdk_subsystem_list sorted_list;
     104                 :            : 
     105                 :       2899 :         TAILQ_INIT(&sorted_list);
     106                 :            :         /* We will move subsystems from the original g_subsystems TAILQ to the temporary
     107                 :            :          * sorted_list one at a time. We can only move a subsystem if it either (a) has no
     108                 :            :          * dependencies, or (b) all of its dependencies have already been moved to the
     109                 :            :          * sorted_list.
     110                 :            :          *
     111                 :            :          * Once all of the subsystems have been moved to the temporary list, we will move
     112                 :            :          * the list as-is back to the original g_subsystems TAILQ - they will now be sorted
     113                 :            :          * in the order which they must be initialized.
     114                 :            :          */
     115         [ +  + ]:       7944 :         while (!TAILQ_EMPTY(&g_subsystems)) {
     116         [ +  + ]:      32279 :                 TAILQ_FOREACH_SAFE(subsystem, &g_subsystems, tailq, subsystem_tmp) {
     117                 :      27234 :                         has_dependency = false;
     118                 :      27234 :                         all_dependencies_met = true;
     119         [ +  + ]:     267667 :                         TAILQ_FOREACH(subsystem_dep, &g_subsystems_deps, tailq) {
     120   [ +  +  -  +  :     246482 :                                 if (strcmp(subsystem->name, subsystem_dep->name) == 0) {
                   +  + ]
     121                 :      28072 :                                         has_dependency = true;
     122         [ +  + ]:      28072 :                                         if (!_subsystem_find(&sorted_list, subsystem_dep->depends_on)) {
     123                 :            :                                                 /* We found a dependency that isn't in the sorted_list yet.
     124                 :            :                                                  * Clear the flag and break from the inner loop, we know
     125                 :            :                                                  * we can't move this subsystem to the sorted_list yet.
     126                 :            :                                                  */
     127                 :       6049 :                                                 all_dependencies_met = false;
     128                 :       6049 :                                                 break;
     129                 :            :                                         }
     130                 :            :                                 }
     131                 :            :                         }
     132                 :            : 
     133   [ +  +  +  + ]:      27234 :                         if (!has_dependency || all_dependencies_met) {
     134         [ +  + ]:      21185 :                                 TAILQ_REMOVE(&g_subsystems, subsystem, tailq);
     135                 :      21185 :                                 TAILQ_INSERT_TAIL(&sorted_list, subsystem, tailq);
     136                 :            :                         }
     137                 :            :                 }
     138                 :            :         }
     139                 :            : 
     140   [ -  +  +  + ]:       2899 :         TAILQ_SWAP(&sorted_list, &g_subsystems, spdk_subsystem, tailq);
     141                 :       2899 : }
     142                 :            : 
     143                 :            : void
     144                 :      24084 : spdk_subsystem_init_next(int rc)
     145                 :            : {
     146         [ -  + ]:      24084 :         assert(spdk_thread_is_app_thread(NULL));
     147                 :            : 
     148                 :            :         /* The initialization is interrupted by the spdk_subsystem_fini, so just return */
     149   [ -  +  -  + ]:      24084 :         if (g_subsystems_init_interrupted) {
     150                 :          0 :                 return;
     151                 :            :         }
     152                 :            : 
     153         [ -  + ]:      24084 :         if (rc) {
     154                 :          0 :                 SPDK_ERRLOG("Init subsystem %s failed\n", g_next_subsystem->name);
     155                 :          0 :                 g_subsystem_start_fn(rc, g_subsystem_start_arg);
     156                 :          0 :                 return;
     157                 :            :         }
     158                 :            : 
     159         [ +  + ]:      24084 :         if (!g_next_subsystem) {
     160                 :       2899 :                 g_next_subsystem = TAILQ_FIRST(&g_subsystems);
     161                 :            :         } else {
     162                 :      21185 :                 g_next_subsystem = TAILQ_NEXT(g_next_subsystem, tailq);
     163                 :            :         }
     164                 :            : 
     165         [ +  + ]:      24084 :         if (!g_next_subsystem) {
     166                 :       2899 :                 g_subsystems_initialized = true;
     167                 :       2899 :                 g_subsystem_start_fn(0, g_subsystem_start_arg);
     168                 :       2899 :                 return;
     169                 :            :         }
     170                 :            : 
     171         [ +  + ]:      21185 :         if (g_next_subsystem->init) {
     172                 :      21113 :                 g_next_subsystem->init();
     173                 :            :         } else {
     174                 :         72 :                 spdk_subsystem_init_next(0);
     175                 :            :         }
     176                 :            : }
     177                 :            : 
     178                 :            : void
     179                 :       2911 : spdk_subsystem_init(spdk_subsystem_init_fn cb_fn, void *cb_arg)
     180                 :            : {
     181                 :            :         struct spdk_subsystem_depend *dep;
     182                 :            : 
     183         [ -  + ]:       2911 :         assert(spdk_thread_is_app_thread(NULL));
     184                 :            : 
     185                 :       2911 :         g_subsystem_start_fn = cb_fn;
     186                 :       2911 :         g_subsystem_start_arg = cb_arg;
     187                 :            : 
     188                 :            :         /* Verify that all dependency name and depends_on subsystems are registered */
     189         [ +  + ]:      24934 :         TAILQ_FOREACH(dep, &g_subsystems_deps, tailq) {
     190         [ +  + ]:      22035 :                 if (!subsystem_find(dep->name)) {
     191                 :          6 :                         SPDK_ERRLOG("subsystem %s is missing\n", dep->name);
     192                 :          6 :                         g_subsystem_start_fn(-1, g_subsystem_start_arg);
     193                 :          6 :                         return;
     194                 :            :                 }
     195         [ +  + ]:      22029 :                 if (!subsystem_find(dep->depends_on)) {
     196                 :          6 :                         SPDK_ERRLOG("subsystem %s dependency %s is missing\n",
     197                 :            :                                     dep->name, dep->depends_on);
     198                 :          6 :                         g_subsystem_start_fn(-1, g_subsystem_start_arg);
     199                 :          6 :                         return;
     200                 :            :                 }
     201                 :            :         }
     202                 :            : 
     203                 :       2899 :         subsystem_sort();
     204                 :            : 
     205                 :       2899 :         spdk_subsystem_init_next(0);
     206                 :            : }
     207                 :            : 
     208                 :            : static void
     209                 :      24074 : subsystem_fini_next(void *arg1)
     210                 :            : {
     211         [ -  + ]:      24074 :         assert(g_fini_thread == spdk_get_thread());
     212                 :            : 
     213         [ +  + ]:      24074 :         if (!g_next_subsystem) {
     214                 :            :                 /* If the initialized flag is false, then we've failed to initialize
     215                 :            :                  * the very first subsystem and no de-init is needed
     216                 :            :                  */
     217   [ +  +  +  + ]:       2961 :                 if (g_subsystems_initialized) {
     218                 :       2886 :                         g_next_subsystem = TAILQ_LAST(&g_subsystems, spdk_subsystem_list);
     219                 :            :                 }
     220                 :            :         } else {
     221   [ -  +  -  +  :      21113 :                 if (g_subsystems_initialized || g_subsystems_init_interrupted) {
             -  -  -  - ]
     222                 :      21113 :                         g_next_subsystem = TAILQ_PREV(g_next_subsystem, spdk_subsystem_list, tailq);
     223                 :            :                 } else {
     224                 :          0 :                         g_subsystems_init_interrupted = true;
     225                 :            :                 }
     226                 :            :         }
     227                 :            : 
     228         [ +  + ]:      24074 :         while (g_next_subsystem) {
     229         [ +  - ]:      21113 :                 if (g_next_subsystem->fini) {
     230                 :      21113 :                         g_next_subsystem->fini();
     231                 :      21113 :                         return;
     232                 :            :                 }
     233                 :          0 :                 g_next_subsystem = TAILQ_PREV(g_next_subsystem, spdk_subsystem_list, tailq);
     234                 :            :         }
     235                 :            : 
     236                 :       2961 :         g_subsystem_stop_fn(g_subsystem_stop_arg);
     237                 :       2961 :         return;
     238                 :            : }
     239                 :            : 
     240                 :            : void
     241                 :      24074 : spdk_subsystem_fini_next(void)
     242                 :            : {
     243         [ -  + ]:      24074 :         if (g_fini_thread != spdk_get_thread()) {
     244                 :          0 :                 spdk_thread_send_msg(g_fini_thread, subsystem_fini_next, NULL);
     245                 :            :         } else {
     246                 :      24074 :                 subsystem_fini_next(NULL);
     247                 :            :         }
     248                 :      24074 : }
     249                 :            : 
     250                 :            : void
     251                 :       2961 : spdk_subsystem_fini(spdk_msg_fn cb_fn, void *cb_arg)
     252                 :            : {
     253                 :       2961 :         g_subsystem_stop_fn = cb_fn;
     254                 :       2961 :         g_subsystem_stop_arg = cb_arg;
     255                 :            : 
     256                 :       2961 :         g_fini_thread = spdk_get_thread();
     257                 :            : 
     258                 :       2961 :         spdk_subsystem_fini_next();
     259                 :       2961 : }
     260                 :            : 
     261                 :            : void
     262                 :       1716 : subsystem_config_json(struct spdk_json_write_ctx *w, struct spdk_subsystem *subsystem)
     263                 :            : {
     264   [ +  -  +  + ]:       1716 :         if (subsystem && subsystem->write_config_json) {
     265                 :       1600 :                 subsystem->write_config_json(w);
     266                 :            :         } else {
     267                 :        116 :                 spdk_json_write_null(w);
     268                 :            :         }
     269                 :       1716 : }

Generated by: LCOV version 1.14