LCOV - code coverage report
Current view: top level - kernel - range.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 41 78 52.6 %
Date: 2022-04-01 13:59:58 Functions: 3 6 50.0 %
Branches: 19 66 28.8 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : /*
       3                 :            :  * Range add and subtract
       4                 :            :  */
       5                 :            : #include <linux/kernel.h>
       6                 :            : #include <linux/init.h>
       7                 :            : #include <linux/sort.h>
       8                 :            : #include <linux/string.h>
       9                 :            : #include <linux/range.h>
      10                 :            : 
      11                 :        390 : int add_range(struct range *range, int az, int nr_range, u64 start, u64 end)
      12                 :            : {
      13         [ #  # ]:          0 :         if (start >= end)
      14                 :            :                 return nr_range;
      15                 :            : 
      16                 :            :         /* Out of slots: */
      17   [ +  -  -  - ]:        390 :         if (nr_range >= az)
      18                 :            :                 return nr_range;
      19                 :            : 
      20                 :        390 :         range[nr_range].start = start;
      21                 :        390 :         range[nr_range].end = end;
      22                 :            : 
      23                 :        390 :         nr_range++;
      24                 :            : 
      25                 :        390 :         return nr_range;
      26                 :            : }
      27                 :            : 
      28                 :        390 : int add_range_with_merge(struct range *range, int az, int nr_range,
      29                 :            :                      u64 start, u64 end)
      30                 :            : {
      31                 :        390 :         int i;
      32                 :            : 
      33         [ +  - ]:        390 :         if (start >= end)
      34                 :            :                 return nr_range;
      35                 :            : 
      36                 :            :         /* get new start/end: */
      37         [ +  + ]:        858 :         for (i = 0; i < nr_range; i++) {
      38                 :        468 :                 u64 common_start, common_end;
      39                 :            : 
      40         [ -  + ]:        468 :                 if (!range[i].end)
      41                 :          0 :                         continue;
      42                 :            : 
      43                 :        468 :                 common_start = max(range[i].start, start);
      44                 :        468 :                 common_end = min(range[i].end, end);
      45         [ +  + ]:        468 :                 if (common_start > common_end)
      46                 :        156 :                         continue;
      47                 :            : 
      48                 :            :                 /* new start/end, will add it back at last */
      49                 :        312 :                 start = min(range[i].start, start);
      50                 :        312 :                 end = max(range[i].end, end);
      51                 :            : 
      52                 :        312 :                 memmove(&range[i], &range[i + 1],
      53                 :        312 :                         (nr_range - (i + 1)) * sizeof(range[i]));
      54                 :        312 :                 range[nr_range - 1].start = 0;
      55                 :        312 :                 range[nr_range - 1].end   = 0;
      56                 :        312 :                 nr_range--;
      57                 :        312 :                 i--;
      58                 :            :         }
      59                 :            : 
      60                 :            :         /* Need to add it: */
      61         [ +  - ]:        390 :         return add_range(range, az, nr_range, start, end);
      62                 :            : }
      63                 :            : 
      64                 :          0 : void subtract_range(struct range *range, int az, u64 start, u64 end)
      65                 :            : {
      66                 :          0 :         int i, j;
      67                 :            : 
      68         [ #  # ]:          0 :         if (start >= end)
      69                 :            :                 return;
      70                 :            : 
      71         [ #  # ]:          0 :         for (j = 0; j < az; j++) {
      72         [ #  # ]:          0 :                 if (!range[j].end)
      73                 :          0 :                         continue;
      74                 :            : 
      75   [ #  #  #  # ]:          0 :                 if (start <= range[j].start && end >= range[j].end) {
      76                 :          0 :                         range[j].start = 0;
      77                 :          0 :                         range[j].end = 0;
      78                 :          0 :                         continue;
      79                 :            :                 }
      80                 :            : 
      81   [ #  #  #  #  :          0 :                 if (start <= range[j].start && end < range[j].end &&
                   #  # ]
      82                 :            :                     range[j].start < end) {
      83                 :          0 :                         range[j].start = end;
      84                 :          0 :                         continue;
      85                 :            :                 }
      86                 :            : 
      87                 :            : 
      88   [ #  #  #  #  :          0 :                 if (start > range[j].start && end >= range[j].end &&
                   #  # ]
      89                 :            :                     range[j].end > start) {
      90                 :          0 :                         range[j].end = start;
      91                 :          0 :                         continue;
      92                 :            :                 }
      93                 :            : 
      94   [ #  #  #  # ]:          0 :                 if (start > range[j].start && end < range[j].end) {
      95                 :            :                         /* Find the new spare: */
      96         [ #  # ]:          0 :                         for (i = 0; i < az; i++) {
      97         [ #  # ]:          0 :                                 if (range[i].end == 0)
      98                 :            :                                         break;
      99                 :            :                         }
     100         [ #  # ]:          0 :                         if (i < az) {
     101                 :          0 :                                 range[i].end = range[j].end;
     102                 :          0 :                                 range[i].start = end;
     103                 :            :                         } else {
     104                 :          0 :                                 pr_err("%s: run out of slot in ranges\n",
     105                 :            :                                         __func__);
     106                 :            :                         }
     107                 :          0 :                         range[j].end = start;
     108                 :          0 :                         continue;
     109                 :            :                 }
     110                 :            :         }
     111                 :            : }
     112                 :            : 
     113                 :        156 : static int cmp_range(const void *x1, const void *x2)
     114                 :            : {
     115                 :        156 :         const struct range *r1 = x1;
     116                 :        156 :         const struct range *r2 = x2;
     117                 :            : 
     118         [ -  + ]:        156 :         if (r1->start < r2->start)
     119                 :            :                 return -1;
     120         [ #  # ]:          0 :         if (r1->start > r2->start)
     121                 :          0 :                 return 1;
     122                 :            :         return 0;
     123                 :            : }
     124                 :            : 
     125                 :        390 : int clean_sort_range(struct range *range, int az)
     126                 :            : {
     127                 :        390 :         int i, j, k = az - 1, nr_range = az;
     128                 :            : 
     129         [ +  - ]:        936 :         for (i = 0; i < k; i++) {
     130         [ +  + ]:        936 :                 if (range[i].end)
     131                 :        546 :                         continue;
     132         [ +  + ]:     124254 :                 for (j = k; j > i; j--) {
     133         [ +  - ]:     123864 :                         if (range[j].end) {
     134                 :            :                                 k = j;
     135                 :            :                                 break;
     136                 :            :                         }
     137                 :            :                 }
     138         [ -  + ]:        390 :                 if (j == i)
     139                 :            :                         break;
     140                 :          0 :                 range[i].start = range[k].start;
     141                 :          0 :                 range[i].end   = range[k].end;
     142                 :          0 :                 range[k].start = 0;
     143                 :          0 :                 range[k].end   = 0;
     144                 :          0 :                 k--;
     145                 :            :         }
     146                 :            :         /* count it */
     147         [ +  - ]:        936 :         for (i = 0; i < az; i++) {
     148         [ +  + ]:        936 :                 if (!range[i].end) {
     149                 :            :                         nr_range = i;
     150                 :            :                         break;
     151                 :            :                 }
     152                 :            :         }
     153                 :            : 
     154                 :            :         /* sort them */
     155                 :        390 :         sort(range, nr_range, sizeof(struct range), cmp_range, NULL);
     156                 :            : 
     157                 :        390 :         return nr_range;
     158                 :            : }
     159                 :            : 
     160                 :          0 : void sort_range(struct range *range, int nr_range)
     161                 :            : {
     162                 :            :         /* sort them */
     163                 :          0 :         sort(range, nr_range, sizeof(struct range), cmp_range, NULL);
     164                 :          0 : }

Generated by: LCOV version 1.14