LCOV - code coverage report
Current view: top level - kernel/sched - isolation.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 4 89 4.5 %
Date: 2022-04-01 13:59:58 Functions: 2 9 22.2 %
Branches: 3 66 4.5 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-only
       2                 :            : /*
       3                 :            :  *  Housekeeping management. Manage the targets for routine code that can run on
       4                 :            :  *  any CPU: unbound workqueues, timers, kthreads and any offloadable work.
       5                 :            :  *
       6                 :            :  * Copyright (C) 2017 Red Hat, Inc., Frederic Weisbecker
       7                 :            :  * Copyright (C) 2017-2018 SUSE, Frederic Weisbecker
       8                 :            :  *
       9                 :            :  */
      10                 :            : #include "sched.h"
      11                 :            : 
      12                 :            : DEFINE_STATIC_KEY_FALSE(housekeeping_overridden);
      13                 :            : EXPORT_SYMBOL_GPL(housekeeping_overridden);
      14                 :            : static cpumask_var_t housekeeping_mask;
      15                 :            : static unsigned int housekeeping_flags;
      16                 :            : 
      17                 :          0 : bool housekeeping_enabled(enum hk_flags flags)
      18                 :            : {
      19                 :          0 :         return !!(housekeeping_flags & flags);
      20                 :            : }
      21                 :            : EXPORT_SYMBOL_GPL(housekeeping_enabled);
      22                 :            : 
      23                 :          0 : int housekeeping_any_cpu(enum hk_flags flags)
      24                 :            : {
      25                 :          0 :         int cpu;
      26                 :            : 
      27   [ #  #  #  # ]:          0 :         if (static_branch_unlikely(&housekeeping_overridden)) {
      28         [ #  # ]:          0 :                 if (housekeeping_flags & flags) {
      29                 :          0 :                         cpu = sched_numa_find_closest(housekeeping_mask, smp_processor_id());
      30         [ #  # ]:          0 :                         if (cpu < nr_cpu_ids)
      31                 :            :                                 return cpu;
      32                 :            : 
      33                 :          0 :                         return cpumask_any_and(housekeeping_mask, cpu_online_mask);
      34                 :            :                 }
      35                 :            :         }
      36                 :          0 :         return smp_processor_id();
      37                 :            : }
      38                 :            : EXPORT_SYMBOL_GPL(housekeeping_any_cpu);
      39                 :            : 
      40                 :        234 : const struct cpumask *housekeeping_cpumask(enum hk_flags flags)
      41                 :            : {
      42   [ +  -  -  + ]:        468 :         if (static_branch_unlikely(&housekeeping_overridden))
      43         [ #  # ]:          0 :                 if (housekeeping_flags & flags)
      44                 :          0 :                         return housekeeping_mask;
      45                 :            :         return cpu_possible_mask;
      46                 :            : }
      47                 :            : EXPORT_SYMBOL_GPL(housekeeping_cpumask);
      48                 :            : 
      49                 :          0 : void housekeeping_affine(struct task_struct *t, enum hk_flags flags)
      50                 :            : {
      51   [ #  #  #  # ]:          0 :         if (static_branch_unlikely(&housekeeping_overridden))
      52         [ #  # ]:          0 :                 if (housekeeping_flags & flags)
      53                 :          0 :                         set_cpus_allowed_ptr(t, housekeeping_mask);
      54                 :          0 : }
      55                 :            : EXPORT_SYMBOL_GPL(housekeeping_affine);
      56                 :            : 
      57                 :          0 : bool housekeeping_test_cpu(int cpu, enum hk_flags flags)
      58                 :            : {
      59   [ #  #  #  # ]:          0 :         if (static_branch_unlikely(&housekeeping_overridden))
      60         [ #  # ]:          0 :                 if (housekeeping_flags & flags)
      61                 :          0 :                         return cpumask_test_cpu(cpu, housekeeping_mask);
      62                 :            :         return true;
      63                 :            : }
      64                 :            : EXPORT_SYMBOL_GPL(housekeeping_test_cpu);
      65                 :            : 
      66                 :         78 : void __init housekeeping_init(void)
      67                 :            : {
      68         [ -  + ]:         78 :         if (!housekeeping_flags)
      69                 :            :                 return;
      70                 :            : 
      71                 :          0 :         static_branch_enable(&housekeeping_overridden);
      72                 :            : 
      73                 :          0 :         if (housekeeping_flags & HK_FLAG_TICK)
      74                 :            :                 sched_tick_offload_init();
      75                 :            : 
      76                 :            :         /* We need at least one CPU to handle housekeeping work */
      77         [ #  # ]:          0 :         WARN_ON_ONCE(cpumask_empty(housekeeping_mask));
      78                 :            : }
      79                 :            : 
      80                 :          0 : static int __init housekeeping_setup(char *str, enum hk_flags flags)
      81                 :            : {
      82                 :          0 :         cpumask_var_t non_housekeeping_mask;
      83                 :          0 :         cpumask_var_t tmp;
      84                 :          0 :         int err;
      85                 :            : 
      86                 :          0 :         alloc_bootmem_cpumask_var(&non_housekeeping_mask);
      87                 :          0 :         err = cpulist_parse(str, non_housekeeping_mask);
      88   [ #  #  #  # ]:          0 :         if (err < 0 || cpumask_last(non_housekeeping_mask) >= nr_cpu_ids) {
      89                 :          0 :                 pr_warn("Housekeeping: nohz_full= or isolcpus= incorrect CPU range\n");
      90                 :          0 :                 free_bootmem_cpumask_var(non_housekeeping_mask);
      91                 :          0 :                 return 0;
      92                 :            :         }
      93                 :            : 
      94         [ #  # ]:          0 :         alloc_bootmem_cpumask_var(&tmp);
      95         [ #  # ]:          0 :         if (!housekeeping_flags) {
      96         [ #  # ]:          0 :                 alloc_bootmem_cpumask_var(&housekeeping_mask);
      97         [ #  # ]:          0 :                 cpumask_andnot(housekeeping_mask,
      98                 :            :                                cpu_possible_mask, non_housekeeping_mask);
      99                 :            : 
     100                 :          0 :                 cpumask_andnot(tmp, cpu_present_mask, non_housekeeping_mask);
     101         [ #  # ]:          0 :                 if (cpumask_empty(tmp)) {
     102                 :          0 :                         pr_warn("Housekeeping: must include one present CPU, "
     103                 :            :                                 "using boot CPU:%d\n", smp_processor_id());
     104                 :          0 :                         __cpumask_set_cpu(smp_processor_id(), housekeeping_mask);
     105                 :          0 :                         __cpumask_clear_cpu(smp_processor_id(), non_housekeeping_mask);
     106                 :            :                 }
     107                 :            :         } else {
     108         [ #  # ]:          0 :                 cpumask_andnot(tmp, cpu_present_mask, non_housekeeping_mask);
     109         [ #  # ]:          0 :                 if (cpumask_empty(tmp))
     110                 :          0 :                         __cpumask_clear_cpu(smp_processor_id(), non_housekeeping_mask);
     111                 :          0 :                 cpumask_andnot(tmp, cpu_possible_mask, non_housekeeping_mask);
     112         [ #  # ]:          0 :                 if (!cpumask_equal(tmp, housekeeping_mask)) {
     113                 :          0 :                         pr_warn("Housekeeping: nohz_full= must match isolcpus=\n");
     114                 :          0 :                         free_bootmem_cpumask_var(tmp);
     115                 :          0 :                         free_bootmem_cpumask_var(non_housekeeping_mask);
     116                 :          0 :                         return 0;
     117                 :            :                 }
     118                 :            :         }
     119         [ #  # ]:          0 :         free_bootmem_cpumask_var(tmp);
     120                 :            : 
     121   [ #  #  #  # ]:          0 :         if ((flags & HK_FLAG_TICK) && !(housekeeping_flags & HK_FLAG_TICK)) {
     122                 :          0 :                 if (IS_ENABLED(CONFIG_NO_HZ_FULL)) {
     123                 :            :                         tick_nohz_full_setup(non_housekeeping_mask);
     124                 :            :                 } else {
     125                 :          0 :                         pr_warn("Housekeeping: nohz unsupported."
     126                 :            :                                 " Build with CONFIG_NO_HZ_FULL\n");
     127                 :          0 :                         free_bootmem_cpumask_var(non_housekeeping_mask);
     128                 :          0 :                         return 0;
     129                 :            :                 }
     130                 :            :         }
     131                 :            : 
     132                 :          0 :         housekeeping_flags |= flags;
     133                 :            : 
     134                 :          0 :         free_bootmem_cpumask_var(non_housekeeping_mask);
     135                 :            : 
     136                 :          0 :         return 1;
     137                 :            : }
     138                 :            : 
     139                 :          0 : static int __init housekeeping_nohz_full_setup(char *str)
     140                 :            : {
     141                 :          0 :         unsigned int flags;
     142                 :            : 
     143                 :          0 :         flags = HK_FLAG_TICK | HK_FLAG_WQ | HK_FLAG_TIMER | HK_FLAG_RCU | HK_FLAG_MISC;
     144                 :            : 
     145                 :          0 :         return housekeeping_setup(str, flags);
     146                 :            : }
     147                 :            : __setup("nohz_full=", housekeeping_nohz_full_setup);
     148                 :            : 
     149                 :          0 : static int __init housekeeping_isolcpus_setup(char *str)
     150                 :            : {
     151                 :          0 :         unsigned int flags = 0;
     152                 :            : 
     153         [ #  # ]:          0 :         while (isalpha(*str)) {
     154         [ #  # ]:          0 :                 if (!strncmp(str, "nohz,", 5)) {
     155                 :          0 :                         str += 5;
     156                 :          0 :                         flags |= HK_FLAG_TICK;
     157                 :          0 :                         continue;
     158                 :            :                 }
     159                 :            : 
     160         [ #  # ]:          0 :                 if (!strncmp(str, "domain,", 7)) {
     161                 :          0 :                         str += 7;
     162                 :          0 :                         flags |= HK_FLAG_DOMAIN;
     163                 :          0 :                         continue;
     164                 :            :                 }
     165                 :            : 
     166         [ #  # ]:          0 :                 if (!strncmp(str, "managed_irq,", 12)) {
     167                 :          0 :                         str += 12;
     168                 :          0 :                         flags |= HK_FLAG_MANAGED_IRQ;
     169                 :          0 :                         continue;
     170                 :            :                 }
     171                 :            : 
     172                 :          0 :                 pr_warn("isolcpus: Error, unknown flag\n");
     173                 :          0 :                 return 0;
     174                 :            :         }
     175                 :            : 
     176                 :            :         /* Default behaviour for isolcpus without flags */
     177         [ #  # ]:          0 :         if (!flags)
     178                 :          0 :                 flags |= HK_FLAG_DOMAIN;
     179                 :            : 
     180                 :          0 :         return housekeeping_setup(str, flags);
     181                 :            : }
     182                 :            : __setup("isolcpus=", housekeeping_isolcpus_setup);

Generated by: LCOV version 1.14