LCOV - code coverage report
Current view: top level - kernel - init.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 43 43 100.0 %
Date: 2022-08-18 11:36:24 Functions: 6 6 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2010-2014 Wind River Systems, Inc.
       3                 :            :  *
       4                 :            :  * SPDX-License-Identifier: Apache-2.0
       5                 :            :  */
       6                 :            : 
       7                 :            : /**
       8                 :            :  * @file
       9                 :            :  * @brief Kernel initialization module
      10                 :            :  *
      11                 :            :  * This module contains routines that are used to initialize the kernel.
      12                 :            :  */
      13                 :            : 
      14                 :            : #include <zephyr.h>
      15                 :            : #include <offsets_short.h>
      16                 :            : #include <kernel.h>
      17                 :            : #include <sys/printk.h>
      18                 :            : #include <debug/stack.h>
      19                 :            : #include <random/rand32.h>
      20                 :            : #include <linker/sections.h>
      21                 :            : #include <toolchain.h>
      22                 :            : #include <kernel_structs.h>
      23                 :            : #include <device.h>
      24                 :            : #include <init.h>
      25                 :            : #include <linker/linker-defs.h>
      26                 :            : #include <ksched.h>
      27                 :            : #include <string.h>
      28                 :            : #include <sys/dlist.h>
      29                 :            : #include <kernel_internal.h>
      30                 :            : #include <drivers/entropy.h>
      31                 :            : #include <logging/log_ctrl.h>
      32                 :            : #include <tracing/tracing.h>
      33                 :            : #include <stdbool.h>
      34                 :            : #include <debug/gcov.h>
      35                 :            : #include <kswap.h>
      36                 :            : #include <timing/timing.h>
      37                 :            : #include <logging/log.h>
      38                 :            : LOG_MODULE_REGISTER(os, CONFIG_KERNEL_LOG_LEVEL);
      39                 :            : 
      40                 :            : /* the only struct z_kernel instance */
      41                 :            : struct z_kernel _kernel;
      42                 :            : 
      43                 :            : /* init/main and idle threads */
      44                 :            : K_THREAD_PINNED_STACK_DEFINE(z_main_stack, CONFIG_MAIN_STACK_SIZE);
      45                 :            : struct k_thread z_main_thread;
      46                 :            : 
      47                 :            : #ifdef CONFIG_MULTITHREADING
      48                 :            : __pinned_bss
      49                 :            : struct k_thread z_idle_threads[CONFIG_MP_NUM_CPUS];
      50                 :            : 
      51                 :            : static K_KERNEL_PINNED_STACK_ARRAY_DEFINE(z_idle_stacks,
      52                 :            :                                           CONFIG_MP_NUM_CPUS,
      53                 :            :                                           CONFIG_IDLE_STACK_SIZE);
      54                 :            : #endif /* CONFIG_MULTITHREADING */
      55                 :            : 
      56                 :            : /*
      57                 :            :  * storage space for the interrupt stack
      58                 :            :  *
      59                 :            :  * Note: This area is used as the system stack during kernel initialization,
      60                 :            :  * since the kernel hasn't yet set up its own stack areas. The dual purposing
      61                 :            :  * of this area is safe since interrupts are disabled until the kernel context
      62                 :            :  * switches to the init thread.
      63                 :            :  */
      64                 :            : K_KERNEL_PINNED_STACK_ARRAY_DEFINE(z_interrupt_stacks,
      65                 :            :                                    CONFIG_MP_NUM_CPUS,
      66                 :            :                                    CONFIG_ISR_STACK_SIZE);
      67                 :            : 
      68                 :            : extern void idle(void *unused1, void *unused2, void *unused3);
      69                 :            : 
      70                 :            : 
      71                 :            : /* LCOV_EXCL_START
      72                 :            :  *
      73                 :            :  * This code is called so early in the boot process that code coverage
      74                 :            :  * doesn't work properly. In addition, not all arches call this code,
      75                 :            :  * some like x86 do this with optimized assembly
      76                 :            :  */
      77                 :            : 
      78                 :            : /**
      79                 :            :  * @brief equivalent of memset() for early boot usage
      80                 :            :  *
      81                 :            :  * Architectures that can't safely use the regular (optimized) memset very
      82                 :            :  * early during boot because e.g. hardware isn't yet sufficiently initialized
      83                 :            :  * may override this with their own safe implementation.
      84                 :            :  */
      85                 :            : __boot_func
      86                 :            : void __weak z_early_memset(void *dst, int c, size_t n)
      87                 :            : {
      88                 :            :         (void) memset(dst, c, n);
      89                 :            : }
      90                 :            : 
      91                 :            : /**
      92                 :            :  * @brief equivalent of memcpy() for early boot usage
      93                 :            :  *
      94                 :            :  * Architectures that can't safely use the regular (optimized) memcpy very
      95                 :            :  * early during boot because e.g. hardware isn't yet sufficiently initialized
      96                 :            :  * may override this with their own safe implementation.
      97                 :            :  */
      98                 :            : __boot_func
      99                 :            : void __weak z_early_memcpy(void *dst, const void *src, size_t n)
     100                 :            : {
     101                 :            :         (void) memcpy(dst, src, n);
     102                 :            : }
     103                 :            : 
     104                 :            : /**
     105                 :            :  * @brief Clear BSS
     106                 :            :  *
     107                 :            :  * This routine clears the BSS region, so all bytes are 0.
     108                 :            :  */
     109                 :            : __boot_func
     110                 :            : void z_bss_zero(void)
     111                 :            : {
     112                 :            :         z_early_memset(__bss_start, 0, __bss_end - __bss_start);
     113                 :            : #if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_ccm), okay)
     114                 :            :         z_early_memset(&__ccm_bss_start, 0,
     115                 :            :                        (uintptr_t) &__ccm_bss_end
     116                 :            :                        - (uintptr_t) &__ccm_bss_start);
     117                 :            : #endif
     118                 :            : #if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_dtcm), okay)
     119                 :            :         z_early_memset(&__dtcm_bss_start, 0,
     120                 :            :                        (uintptr_t) &__dtcm_bss_end
     121                 :            :                        - (uintptr_t) &__dtcm_bss_start);
     122                 :            : #endif
     123                 :            : #if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_ocm), okay)
     124                 :            :         z_early_memset(&__ocm_bss_start, 0,
     125                 :            :                        (uintptr_t) &__ocm_bss_end
     126                 :            :                        - (uintptr_t) &__ocm_bss_start);
     127                 :            : #endif
     128                 :            : #ifdef CONFIG_CODE_DATA_RELOCATION
     129                 :            :         extern void bss_zeroing_relocation(void);
     130                 :            : 
     131                 :            :         bss_zeroing_relocation();
     132                 :            : #endif  /* CONFIG_CODE_DATA_RELOCATION */
     133                 :            : #ifdef CONFIG_COVERAGE_GCOV
     134                 :            :         z_early_memset(&__gcov_bss_start, 0,
     135                 :            :                        ((uintptr_t) &__gcov_bss_end - (uintptr_t) &__gcov_bss_start));
     136                 :            : #endif
     137                 :            : }
     138                 :            : 
     139                 :            : #ifdef CONFIG_LINKER_USE_BOOT_SECTION
     140                 :            : /**
     141                 :            :  * @brief Clear BSS within the bot region
     142                 :            :  *
     143                 :            :  * This routine clears the BSS within the boot region.
     144                 :            :  * This is separate from z_bss_zero() as boot region may
     145                 :            :  * contain symbols required for the boot process before
     146                 :            :  * paging is initialized.
     147                 :            :  */
     148                 :            : __boot_func
     149                 :            : void z_bss_zero_boot(void)
     150                 :            : {
     151                 :            :         z_early_memset(&lnkr_boot_bss_start, 0,
     152                 :            :                        (uintptr_t)&lnkr_boot_bss_end
     153                 :            :                        - (uintptr_t)&lnkr_boot_bss_start);
     154                 :            : }
     155                 :            : #endif /* CONFIG_LINKER_USE_BOOT_SECTION */
     156                 :            : 
     157                 :            : #ifdef CONFIG_LINKER_USE_PINNED_SECTION
     158                 :            : /**
     159                 :            :  * @brief Clear BSS within the pinned region
     160                 :            :  *
     161                 :            :  * This routine clears the BSS within the pinned region.
     162                 :            :  * This is separate from z_bss_zero() as pinned region may
     163                 :            :  * contain symbols required for the boot process before
     164                 :            :  * paging is initialized.
     165                 :            :  */
     166                 :            : #ifdef CONFIG_LINKER_USE_BOOT_SECTION
     167                 :            : __boot_func
     168                 :            : #else
     169                 :            : __pinned_func
     170                 :            : #endif
     171                 :            : void z_bss_zero_pinned(void)
     172                 :            : {
     173                 :            :         z_early_memset(&lnkr_pinned_bss_start, 0,
     174                 :            :                        (uintptr_t)&lnkr_pinned_bss_end
     175                 :            :                        - (uintptr_t)&lnkr_pinned_bss_start);
     176                 :            : }
     177                 :            : #endif /* CONFIG_LINKER_USE_PINNED_SECTION */
     178                 :            : 
     179                 :            : #ifdef CONFIG_STACK_CANARIES
     180                 :            : extern volatile uintptr_t __stack_chk_guard;
     181                 :            : #endif /* CONFIG_STACK_CANARIES */
     182                 :            : 
     183                 :            : /* LCOV_EXCL_STOP */
     184                 :            : 
     185                 :            : __pinned_bss
     186                 :            : bool z_sys_post_kernel;
     187                 :            : 
     188                 :            : extern void boot_banner(void);
     189                 :            : 
     190                 :            : /**
     191                 :            :  * @brief Mainline for kernel's background thread
     192                 :            :  *
     193                 :            :  * This routine completes kernel initialization by invoking the remaining
     194                 :            :  * init functions, then invokes application's main() routine.
     195                 :            :  */
     196                 :            : __boot_func
     197                 :          1 : static void bg_thread_main(void *unused1, void *unused2, void *unused3)
     198                 :            : {
     199                 :            :         ARG_UNUSED(unused1);
     200                 :            :         ARG_UNUSED(unused2);
     201                 :            :         ARG_UNUSED(unused3);
     202                 :            : 
     203                 :            : #ifdef CONFIG_MMU
     204                 :            :         /* Invoked here such that backing store or eviction algorithms may
     205                 :            :          * initialize kernel objects, and that all POST_KERNEL and later tasks
     206                 :            :          * may perform memory management tasks (except for z_phys_map() which
     207                 :            :          * is allowed at any time)
     208                 :            :          */
     209                 :            :         z_mem_manage_init();
     210                 :            : #endif /* CONFIG_MMU */
     211                 :          1 :         z_sys_post_kernel = true;
     212                 :            : 
     213                 :          1 :         z_sys_init_run_level(_SYS_INIT_LEVEL_POST_KERNEL);
     214                 :            : #if CONFIG_STACK_POINTER_RANDOM
     215                 :            :         z_stack_adjust_initialized = 1;
     216                 :            : #endif
     217                 :          1 :         boot_banner();
     218                 :            : 
     219                 :            : #if defined(CONFIG_CPLUSPLUS) && !defined(CONFIG_ARCH_POSIX)
     220                 :            :         void z_cpp_init_static(void);
     221                 :          1 :         z_cpp_init_static();
     222                 :            : #endif
     223                 :            : 
     224                 :            :         /* Final init level before app starts */
     225                 :          1 :         z_sys_init_run_level(_SYS_INIT_LEVEL_APPLICATION);
     226                 :            : 
     227                 :          1 :         z_init_static_threads();
     228                 :            : 
     229                 :            : #ifdef CONFIG_KERNEL_COHERENCE
     230                 :            :         __ASSERT_NO_MSG(arch_mem_coherent(&_kernel));
     231                 :            : #endif
     232                 :            : 
     233                 :            : #ifdef CONFIG_SMP
     234                 :            :         if (!IS_ENABLED(CONFIG_SMP_BOOT_DELAY)) {
     235                 :            :                 z_smp_init();
     236                 :            :         }
     237                 :            :         z_sys_init_run_level(_SYS_INIT_LEVEL_SMP);
     238                 :            : #endif
     239                 :            : 
     240                 :            : #ifdef CONFIG_MMU
     241                 :            :         z_mem_manage_boot_finish();
     242                 :            : #endif /* CONFIG_MMU */
     243                 :            : 
     244                 :            :         extern void main(void);
     245                 :            : 
     246                 :          1 :         main();
     247                 :            : 
     248                 :            :         /* Mark nonessential since main() has no more work to do */
     249                 :          1 :         z_main_thread.base.user_options &= ~K_ESSENTIAL;
     250                 :            : 
     251                 :            : #ifdef CONFIG_COVERAGE_DUMP
     252                 :            :         /* Dump coverage data once the main() has exited. */
     253                 :          1 :         gcov_coverage_dump();
     254                 :            : #endif
     255                 :            : } /* LCOV_EXCL_LINE ... because we just dumped final coverage data */
     256                 :            : 
     257                 :            : #if defined(CONFIG_MULTITHREADING)
     258                 :            : __boot_func
     259                 :          1 : static void init_idle_thread(int i)
     260                 :            : {
     261                 :          1 :         struct k_thread *thread = &z_idle_threads[i];
     262                 :          1 :         k_thread_stack_t *stack = z_idle_stacks[i];
     263                 :            : 
     264                 :            : #ifdef CONFIG_THREAD_NAME
     265                 :            : 
     266                 :            : #if CONFIG_MP_NUM_CPUS > 1
     267                 :            :         char tname[8];
     268                 :            :         snprintk(tname, 8, "idle %02d", i);
     269                 :            : #else
     270                 :          1 :         char *tname = "idle";
     271                 :            : #endif
     272                 :            : 
     273                 :            : #else
     274                 :            :         char *tname = NULL;
     275                 :            : #endif /* CONFIG_THREAD_NAME */
     276                 :            : 
     277                 :          1 :         z_setup_new_thread(thread, stack,
     278                 :          1 :                           CONFIG_IDLE_STACK_SIZE, idle, &_kernel.cpus[i],
     279                 :            :                           NULL, NULL, K_IDLE_PRIO, K_ESSENTIAL,
     280                 :            :                           tname);
     281                 :          1 :         z_mark_thread_as_started(thread);
     282                 :            : 
     283                 :            : #ifdef CONFIG_SMP
     284                 :            :         thread->base.is_idle = 1U;
     285                 :            : #endif
     286                 :          1 : }
     287                 :            : 
     288                 :          1 : void z_init_cpu(int id)
     289                 :            : {
     290                 :          1 :         init_idle_thread(id);
     291                 :          1 :         _kernel.cpus[id].idle_thread = &z_idle_threads[id];
     292                 :          1 :         _kernel.cpus[id].id = id;
     293                 :          1 :         _kernel.cpus[id].irq_stack =
     294                 :          1 :                 (Z_KERNEL_STACK_BUFFER(z_interrupt_stacks[id]) +
     295                 :            :                  K_KERNEL_STACK_SIZEOF(z_interrupt_stacks[id]));
     296                 :            : #ifdef CONFIG_SCHED_THREAD_USAGE_ALL
     297                 :            :         _kernel.cpus[id].usage.track_usage =
     298                 :            :                 CONFIG_SCHED_THREAD_USAGE_AUTO_ENABLE;
     299                 :            : #endif
     300                 :          1 : }
     301                 :            : 
     302                 :            : /**
     303                 :            :  *
     304                 :            :  * @brief Initializes kernel data structures
     305                 :            :  *
     306                 :            :  * This routine initializes various kernel data structures, including
     307                 :            :  * the init and idle threads and any architecture-specific initialization.
     308                 :            :  *
     309                 :            :  * Note that all fields of "_kernel" are set to zero on entry, which may
     310                 :            :  * be all the initialization many of them require.
     311                 :            :  *
     312                 :            :  * @return initial stack pointer for the main thread
     313                 :            :  */
     314                 :            : __boot_func
     315                 :          1 : static char *prepare_multithreading(void)
     316                 :            : {
     317                 :            :         char *stack_ptr;
     318                 :            : 
     319                 :            :         /* _kernel.ready_q is all zeroes */
     320                 :          1 :         z_sched_init();
     321                 :            : 
     322                 :            : #ifndef CONFIG_SMP
     323                 :            :         /*
     324                 :            :          * prime the cache with the main thread since:
     325                 :            :          *
     326                 :            :          * - the cache can never be NULL
     327                 :            :          * - the main thread will be the one to run first
     328                 :            :          * - no other thread is initialized yet and thus their priority fields
     329                 :            :          *   contain garbage, which would prevent the cache loading algorithm
     330                 :            :          *   to work as intended
     331                 :            :          */
     332                 :          1 :         _kernel.ready_q.cache = &z_main_thread;
     333                 :            : #endif
     334                 :          1 :         stack_ptr = z_setup_new_thread(&z_main_thread, z_main_stack,
     335                 :            :                                        CONFIG_MAIN_STACK_SIZE, bg_thread_main,
     336                 :            :                                        NULL, NULL, NULL,
     337                 :            :                                        CONFIG_MAIN_THREAD_PRIORITY,
     338                 :            :                                        K_ESSENTIAL, "main");
     339                 :          1 :         z_mark_thread_as_started(&z_main_thread);
     340                 :          1 :         z_ready_thread(&z_main_thread);
     341                 :            : 
     342                 :          1 :         z_init_cpu(0);
     343                 :            : 
     344                 :          1 :         return stack_ptr;
     345                 :            : }
     346                 :            : 
     347                 :            : __boot_func
     348                 :          1 : static FUNC_NORETURN void switch_to_main_thread(char *stack_ptr)
     349                 :            : {
     350                 :            : #ifdef CONFIG_ARCH_HAS_CUSTOM_SWAP_TO_MAIN
     351                 :          1 :         arch_switch_to_main_thread(&z_main_thread, stack_ptr, bg_thread_main);
     352                 :            : #else
     353                 :            :         ARG_UNUSED(stack_ptr);
     354                 :            :         /*
     355                 :            :          * Context switch to main task (entry function is _main()): the
     356                 :            :          * current fake thread is not on a wait queue or ready queue, so it
     357                 :            :          * will never be rescheduled in.
     358                 :            :          */
     359                 :            :         z_swap_unlocked();
     360                 :            : #endif
     361                 :            :         CODE_UNREACHABLE; /* LCOV_EXCL_LINE */
     362                 :            : }
     363                 :            : #endif /* CONFIG_MULTITHREADING */
     364                 :            : 
     365                 :            : #if defined(CONFIG_ENTROPY_HAS_DRIVER) || defined(CONFIG_TEST_RANDOM_GENERATOR)
     366                 :            : __boot_func
     367                 :            : void z_early_boot_rand_get(uint8_t *buf, size_t length)
     368                 :            : {
     369                 :            : #ifdef CONFIG_ENTROPY_HAS_DRIVER
     370                 :            :         const struct device *entropy = DEVICE_DT_GET_OR_NULL(DT_CHOSEN(zephyr_entropy));
     371                 :            :         int rc;
     372                 :            : 
     373                 :            :         if (!device_is_ready(entropy)) {
     374                 :            :                 goto sys_rand_fallback;
     375                 :            :         }
     376                 :            : 
     377                 :            :         /* Try to see if driver provides an ISR-specific API */
     378                 :            :         rc = entropy_get_entropy_isr(entropy, buf, length, ENTROPY_BUSYWAIT);
     379                 :            :         if (rc == -ENOTSUP) {
     380                 :            :                 /* Driver does not provide an ISR-specific API, assume it can
     381                 :            :                  * be called from ISR context
     382                 :            :                  */
     383                 :            :                 rc = entropy_get_entropy(entropy, buf, length);
     384                 :            :         }
     385                 :            : 
     386                 :            :         if (rc >= 0) {
     387                 :            :                 return;
     388                 :            :         }
     389                 :            : 
     390                 :            :         /* Fall through to fallback */
     391                 :            : 
     392                 :            : sys_rand_fallback:
     393                 :            : #endif
     394                 :            : 
     395                 :            :         /* FIXME: this assumes sys_rand32_get() won't use any synchronization
     396                 :            :          * primitive, like semaphores or mutexes.  It's too early in the boot
     397                 :            :          * process to use any of them.  Ideally, only the path where entropy
     398                 :            :          * devices are available should be built, this is only a fallback for
     399                 :            :          * those devices without a HWRNG entropy driver.
     400                 :            :          */
     401                 :            :         sys_rand_get(buf, length);
     402                 :            : }
     403                 :            : /* defined(CONFIG_ENTROPY_HAS_DRIVER) || defined(CONFIG_TEST_RANDOM_GENERATOR) */
     404                 :            : #endif
     405                 :            : 
     406                 :            : /**
     407                 :            :  *
     408                 :            :  * @brief Initialize kernel
     409                 :            :  *
     410                 :            :  * This routine is invoked when the system is ready to run C code. The
     411                 :            :  * processor must be running in 32-bit mode, and the BSS must have been
     412                 :            :  * cleared/zeroed.
     413                 :            :  *
     414                 :            :  * @return Does not return
     415                 :            :  */
     416                 :            : __boot_func
     417                 :          1 : FUNC_NORETURN void z_cstart(void)
     418                 :            : {
     419                 :            :         /* gcov hook needed to get the coverage report.*/
     420                 :          1 :         gcov_static_init();
     421                 :            : 
     422                 :            :         /* perform any architecture-specific initialization */
     423                 :          1 :         arch_kernel_init();
     424                 :            : 
     425                 :            :         LOG_CORE_INIT();
     426                 :            : 
     427                 :            : #if defined(CONFIG_MULTITHREADING)
     428                 :            :         /* Note: The z_ready_thread() call in prepare_multithreading() requires
     429                 :            :          * a dummy thread even if CONFIG_ARCH_HAS_CUSTOM_SWAP_TO_MAIN=y
     430                 :            :          */
     431                 :            :         struct k_thread dummy_thread;
     432                 :            : 
     433                 :          1 :         z_dummy_thread_init(&dummy_thread);
     434                 :            : #endif
     435                 :            :         /* do any necessary initialization of static devices */
     436                 :          1 :         z_device_state_init();
     437                 :            : 
     438                 :            :         /* perform basic hardware initialization */
     439                 :          1 :         z_sys_init_run_level(_SYS_INIT_LEVEL_PRE_KERNEL_1);
     440                 :          1 :         z_sys_init_run_level(_SYS_INIT_LEVEL_PRE_KERNEL_2);
     441                 :            : 
     442                 :            : #ifdef CONFIG_STACK_CANARIES
     443                 :            :         uintptr_t stack_guard;
     444                 :            : 
     445                 :            :         z_early_boot_rand_get((uint8_t *)&stack_guard, sizeof(stack_guard));
     446                 :            :         __stack_chk_guard = stack_guard;
     447                 :            :         __stack_chk_guard <<= 8;
     448                 :            : #endif  /* CONFIG_STACK_CANARIES */
     449                 :            : 
     450                 :            : #ifdef CONFIG_TIMING_FUNCTIONS_NEED_AT_BOOT
     451                 :            :         timing_init();
     452                 :            :         timing_start();
     453                 :            : #endif
     454                 :            : 
     455                 :            : #ifdef CONFIG_MULTITHREADING
     456                 :          1 :         switch_to_main_thread(prepare_multithreading());
     457                 :            : #else
     458                 :            : #ifdef ARCH_SWITCH_TO_MAIN_NO_MULTITHREADING
     459                 :            :         /* Custom ARCH-specific routine to switch to main()
     460                 :            :          * in the case of no multi-threading.
     461                 :            :          */
     462                 :            :         ARCH_SWITCH_TO_MAIN_NO_MULTITHREADING(bg_thread_main,
     463                 :            :                 NULL, NULL, NULL);
     464                 :            : #else
     465                 :            :         bg_thread_main(NULL, NULL, NULL);
     466                 :            : 
     467                 :            :         /* LCOV_EXCL_START
     468                 :            :          * We've already dumped coverage data at this point.
     469                 :            :          */
     470                 :            :         irq_lock();
     471                 :            :         while (true) {
     472                 :            :         }
     473                 :            :         /* LCOV_EXCL_STOP */
     474                 :            : #endif
     475                 :            : #endif /* CONFIG_MULTITHREADING */
     476                 :            : 
     477                 :            :         /*
     478                 :            :          * Compiler can't tell that the above routines won't return and issues
     479                 :            :          * a warning unless we explicitly tell it that control never gets this
     480                 :            :          * far.
     481                 :            :          */
     482                 :            : 
     483                 :            :         CODE_UNREACHABLE; /* LCOV_EXCL_LINE */
     484                 :            : }

Generated by: LCOV version 1.14