LCOV - code coverage report
Current view: top level - lib/os - bitarray.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 265 0.0 %
Date: 2022-08-18 11:36:24 Functions: 0 17 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 152 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2021 Intel Corporation
       3                 :            :  *
       4                 :            :  * SPDX-License-Identifier: Apache-2.0
       5                 :            :  */
       6                 :            : 
       7                 :            : #include <errno.h>
       8                 :            : #include <stddef.h>
       9                 :            : #include <stdbool.h>
      10                 :            : #include <stdio.h>
      11                 :            : #include <sys/bitarray.h>
      12                 :            : #include <sys/check.h>
      13                 :            : #include <sys/sys_io.h>
      14                 :            : 
      15                 :            : /* Number of bits represented by one bundle */
      16                 :            : #define bundle_bitness(ba)      (sizeof(ba->bundles[0]) * 8)
      17                 :            : 
      18                 :            : struct bundle_data {
      19                 :            :          /* Start and end index of bundles */
      20                 :            :         size_t sidx, eidx;
      21                 :            : 
      22                 :            :          /* Offset inside start and end bundles */
      23                 :            :         size_t soff, eoff;
      24                 :            : 
      25                 :            :          /* Masks for start/end bundles */
      26                 :            :         uint32_t smask, emask;
      27                 :            : };
      28                 :            : 
      29                 :          0 : static void setup_bundle_data(sys_bitarray_t *bitarray,
      30                 :            :                               struct bundle_data *bd,
      31                 :            :                               size_t offset, size_t num_bits)
      32                 :            : {
      33                 :          0 :         bd->sidx = offset / bundle_bitness(bitarray);
      34                 :          0 :         bd->soff = offset % bundle_bitness(bitarray);
      35                 :            : 
      36                 :          0 :         bd->eidx = (offset + num_bits - 1) / bundle_bitness(bitarray);
      37                 :          0 :         bd->eoff = (offset + num_bits - 1) % bundle_bitness(bitarray);
      38                 :            : 
      39                 :          0 :         bd->smask = ~(BIT(bd->soff) - 1);
      40                 :          0 :         bd->emask = (BIT(bd->eoff) - 1) | BIT(bd->eoff);
      41                 :            : 
      42         [ #  # ]:          0 :         if (bd->sidx == bd->eidx) {
      43                 :            :                 /* The region lies within the same bundle. So combine the masks. */
      44                 :          0 :                 bd->smask &= bd->emask;
      45                 :            :         }
      46                 :          0 : }
      47                 :            : 
      48                 :            : /*
      49                 :            :  * Find out if the bits in a region is all set or all clear.
      50                 :            :  *
      51                 :            :  * @param[in]  bitarray  Bitarray struct
      52                 :            :  * @param[in]  offset    Starting bit location
      53                 :            :  * @param[in]  num_bits  Number of bits in the region
      54                 :            :  * @param[in]  match_set True if matching all set bits,
      55                 :            :  *                       False if matching all cleared bits
      56                 :            :  * @param[out] bd        Data related to matching which can be
      57                 :            :  *                       used later to find out where the region
      58                 :            :  *                       lies in the bitarray bundles.
      59                 :            :  * @param[out] mismatch  Offset to the mismatched bit.
      60                 :            :  *                       Can be NULL.
      61                 :            :  *
      62                 :            :  * @retval     true      If all bits are set or cleared
      63                 :            :  * @retval     false     Not all bits are set or cleared
      64                 :            :  */
      65                 :          0 : static bool match_region(sys_bitarray_t *bitarray, size_t offset,
      66                 :            :                          size_t num_bits, bool match_set,
      67                 :            :                          struct bundle_data *bd,
      68                 :            :                          size_t *mismatch)
      69                 :            : {
      70                 :            :         int idx;
      71                 :            :         uint32_t bundle;
      72                 :            :         uint32_t mismatch_bundle;
      73                 :            :         size_t mismatch_bundle_idx;
      74                 :            :         size_t mismatch_bit_off;
      75                 :            : 
      76                 :          0 :         setup_bundle_data(bitarray, bd, offset, num_bits);
      77                 :            : 
      78         [ #  # ]:          0 :         if (bd->sidx == bd->eidx) {
      79                 :          0 :                 bundle = bitarray->bundles[bd->sidx];
      80         [ #  # ]:          0 :                 if (!match_set) {
      81                 :          0 :                         bundle = ~bundle;
      82                 :            :                 }
      83                 :            : 
      84         [ #  # ]:          0 :                 if ((bundle & bd->smask) != bd->smask) {
      85                 :            :                         /* Not matching to mask. */
      86                 :          0 :                         mismatch_bundle = ~bundle & bd->smask;
      87                 :          0 :                         mismatch_bundle_idx = bd->sidx;
      88                 :          0 :                         goto mismatch;
      89                 :            :                 } else {
      90                 :            :                         /* Matching to mask. */
      91                 :          0 :                         goto out;
      92                 :            :                 }
      93                 :            :         }
      94                 :            : 
      95                 :            :         /* Region lies in a number of bundles. Need to loop through them. */
      96                 :            : 
      97                 :            :         /* Start of bundles */
      98                 :          0 :         bundle = bitarray->bundles[bd->sidx];
      99         [ #  # ]:          0 :         if (!match_set) {
     100                 :          0 :                 bundle = ~bundle;
     101                 :            :         }
     102                 :            : 
     103         [ #  # ]:          0 :         if ((bundle & bd->smask) != bd->smask) {
     104                 :            :                 /* Start bundle not matching to mask. */
     105                 :          0 :                 mismatch_bundle = ~bundle & bd->smask;
     106                 :          0 :                 mismatch_bundle_idx = bd->sidx;
     107                 :          0 :                 goto mismatch;
     108                 :            :         }
     109                 :            : 
     110                 :            :         /* End of bundles */
     111                 :          0 :         bundle = bitarray->bundles[bd->eidx];
     112         [ #  # ]:          0 :         if (!match_set) {
     113                 :          0 :                 bundle = ~bundle;
     114                 :            :         }
     115                 :            : 
     116         [ #  # ]:          0 :         if ((bundle & bd->emask) != bd->emask) {
     117                 :            :                 /* End bundle not matching to mask. */
     118                 :          0 :                 mismatch_bundle = ~bundle & bd->emask;
     119                 :          0 :                 mismatch_bundle_idx = bd->eidx;
     120                 :          0 :                 goto mismatch;
     121                 :            :         }
     122                 :            : 
     123                 :            :         /* In-between bundles */
     124         [ #  # ]:          0 :         for (idx = bd->sidx + 1; idx < bd->eidx; idx++) {
     125                 :            :                 /* Note that this is opposite from above so that
     126                 :            :                  * we are simply checking if bundle == 0.
     127                 :            :                  */
     128                 :          0 :                 bundle = bitarray->bundles[idx];
     129         [ #  # ]:          0 :                 if (match_set) {
     130                 :          0 :                         bundle = ~bundle;
     131                 :            :                 }
     132                 :            : 
     133         [ #  # ]:          0 :                 if (bundle != 0U) {
     134                 :            :                         /* Bits in "between bundles" do not match */
     135                 :          0 :                         mismatch_bundle = ~bundle;
     136                 :          0 :                         mismatch_bundle_idx = idx;
     137                 :          0 :                         goto mismatch;
     138                 :            :                 }
     139                 :            :         }
     140                 :            : 
     141                 :          0 : out:
     142                 :            :         /* All bits in region matched. */
     143                 :          0 :         return true;
     144                 :            : 
     145                 :          0 : mismatch:
     146         [ #  # ]:          0 :         if (mismatch != NULL) {
     147                 :            :                 /* Must have at least 1 bit set to indicate
     148                 :            :                  * where the mismatch is.
     149                 :            :                  */
     150         [ #  # ]:          0 :                 __ASSERT_NO_MSG(mismatch_bundle != 0);
     151                 :            : 
     152                 :          0 :                 mismatch_bit_off = find_lsb_set(mismatch_bundle) - 1;
     153                 :          0 :                 mismatch_bit_off += mismatch_bundle_idx *
     154                 :            :                                     bundle_bitness(bitarray);
     155                 :          0 :                 *mismatch = (uint32_t)mismatch_bit_off;
     156                 :            :         }
     157                 :          0 :         return false;
     158                 :            : }
     159                 :            : 
     160                 :            : /*
     161                 :            :  * Set or clear a region of bits.
     162                 :            :  *
     163                 :            :  * @param bitarray Bitarray struct
     164                 :            :  * @param offset   Starting bit location
     165                 :            :  * @param num_bits Number of bits in the region
     166                 :            :  * @param to_set   True if to set all bits.
     167                 :            :  *                 False if to clear all bits.
     168                 :            :  * @param bd       Bundle data. Can reuse the output from
     169                 :            :  *                 match_region(). NULL if there is no
     170                 :            :  *                 prior call to match_region().
     171                 :            :  */
     172                 :          0 : static void set_region(sys_bitarray_t *bitarray, size_t offset,
     173                 :            :                        size_t num_bits, bool to_set,
     174                 :            :                        struct bundle_data *bd)
     175                 :            : {
     176                 :            :         int idx;
     177                 :            :         struct bundle_data bdata;
     178                 :            : 
     179         [ #  # ]:          0 :         if (bd == NULL) {
     180                 :          0 :                 bd = &bdata;
     181                 :          0 :                 setup_bundle_data(bitarray, bd, offset, num_bits);
     182                 :            :         }
     183                 :            : 
     184         [ #  # ]:          0 :         if (bd->sidx == bd->eidx) {
     185                 :            :                 /* Start/end at same bundle */
     186         [ #  # ]:          0 :                 if (to_set) {
     187                 :          0 :                         bitarray->bundles[bd->sidx] |= bd->smask;
     188                 :            :                 } else {
     189                 :          0 :                         bitarray->bundles[bd->sidx] &= ~bd->smask;
     190                 :            :                 }
     191                 :            :         } else {
     192                 :            :                 /* Start/end at different bundle.
     193                 :            :                  * So set/clear the bits in start and end bundles
     194                 :            :                  * separately. For in-between bundles,
     195                 :            :                  * set/clear all bits.
     196                 :            :                  */
     197         [ #  # ]:          0 :                 if (to_set) {
     198                 :          0 :                         bitarray->bundles[bd->sidx] |= bd->smask;
     199                 :          0 :                         bitarray->bundles[bd->eidx] |= bd->emask;
     200         [ #  # ]:          0 :                         for (idx = bd->sidx + 1; idx < bd->eidx; idx++) {
     201                 :          0 :                                 bitarray->bundles[idx] = ~0U;
     202                 :            :                         }
     203                 :            :                 } else {
     204                 :          0 :                         bitarray->bundles[bd->sidx] &= ~bd->smask;
     205                 :          0 :                         bitarray->bundles[bd->eidx] &= ~bd->emask;
     206         [ #  # ]:          0 :                         for (idx = bd->sidx + 1; idx < bd->eidx; idx++) {
     207                 :          0 :                                 bitarray->bundles[idx] = 0U;
     208                 :            :                         }
     209                 :            :                 }
     210                 :            :         }
     211                 :          0 : }
     212                 :            : 
     213                 :          0 : int sys_bitarray_set_bit(sys_bitarray_t *bitarray, size_t bit)
     214                 :            : {
     215                 :            :         k_spinlock_key_t key;
     216                 :            :         int ret;
     217                 :            :         size_t idx, off;
     218                 :            : 
     219                 :          0 :         key = k_spin_lock(&bitarray->lock);
     220                 :            : 
     221         [ #  # ]:          0 :         __ASSERT_NO_MSG(bitarray != NULL);
     222         [ #  # ]:          0 :         __ASSERT_NO_MSG(bitarray->num_bits > 0);
     223                 :            : 
     224         [ #  # ]:          0 :         if (bit >= bitarray->num_bits) {
     225                 :          0 :                 ret = -EINVAL;
     226                 :          0 :                 goto out;
     227                 :            :         }
     228                 :            : 
     229                 :          0 :         idx = bit / bundle_bitness(bitarray);
     230                 :          0 :         off = bit % bundle_bitness(bitarray);
     231                 :            : 
     232                 :          0 :         bitarray->bundles[idx] |= BIT(off);
     233                 :            : 
     234                 :          0 :         ret = 0;
     235                 :            : 
     236                 :          0 : out:
     237                 :          0 :         k_spin_unlock(&bitarray->lock, key);
     238                 :          0 :         return ret;
     239                 :            : }
     240                 :            : 
     241                 :          0 : int sys_bitarray_clear_bit(sys_bitarray_t *bitarray, size_t bit)
     242                 :            : {
     243                 :            :         k_spinlock_key_t key;
     244                 :            :         int ret;
     245                 :            :         size_t idx, off;
     246                 :            : 
     247         [ #  # ]:          0 :         __ASSERT_NO_MSG(bitarray != NULL);
     248         [ #  # ]:          0 :         __ASSERT_NO_MSG(bitarray->num_bits > 0);
     249                 :            : 
     250                 :          0 :         key = k_spin_lock(&bitarray->lock);
     251                 :            : 
     252         [ #  # ]:          0 :         if (bit >= bitarray->num_bits) {
     253                 :          0 :                 ret = -EINVAL;
     254                 :          0 :                 goto out;
     255                 :            :         }
     256                 :            : 
     257                 :          0 :         idx = bit / bundle_bitness(bitarray);
     258                 :          0 :         off = bit % bundle_bitness(bitarray);
     259                 :            : 
     260                 :          0 :         bitarray->bundles[idx] &= ~BIT(off);
     261                 :            : 
     262                 :          0 :         ret = 0;
     263                 :            : 
     264                 :          0 : out:
     265                 :          0 :         k_spin_unlock(&bitarray->lock, key);
     266                 :          0 :         return ret;
     267                 :            : }
     268                 :            : 
     269                 :          0 : int sys_bitarray_test_bit(sys_bitarray_t *bitarray, size_t bit, int *val)
     270                 :            : {
     271                 :            :         k_spinlock_key_t key;
     272                 :            :         int ret;
     273                 :            :         size_t idx, off;
     274                 :            : 
     275         [ #  # ]:          0 :         __ASSERT_NO_MSG(bitarray != NULL);
     276         [ #  # ]:          0 :         __ASSERT_NO_MSG(bitarray->num_bits > 0);
     277                 :            : 
     278                 :          0 :         key = k_spin_lock(&bitarray->lock);
     279                 :            : 
     280         [ #  # ]:          0 :         CHECKIF(val == NULL) {
     281                 :          0 :                 ret = -EINVAL;
     282                 :          0 :                 goto out;
     283                 :            :         }
     284                 :            : 
     285         [ #  # ]:          0 :         if (bit >= bitarray->num_bits) {
     286                 :          0 :                 ret = -EINVAL;
     287                 :          0 :                 goto out;
     288                 :            :         }
     289                 :            : 
     290                 :          0 :         idx = bit / bundle_bitness(bitarray);
     291                 :          0 :         off = bit % bundle_bitness(bitarray);
     292                 :            : 
     293         [ #  # ]:          0 :         if ((bitarray->bundles[idx] & BIT(off)) != 0) {
     294                 :          0 :                 *val = 1;
     295                 :            :         } else {
     296                 :          0 :                 *val = 0;
     297                 :            :         }
     298                 :            : 
     299                 :          0 :         ret = 0;
     300                 :            : 
     301                 :          0 : out:
     302                 :          0 :         k_spin_unlock(&bitarray->lock, key);
     303                 :          0 :         return ret;
     304                 :            : }
     305                 :            : 
     306                 :          0 : int sys_bitarray_test_and_set_bit(sys_bitarray_t *bitarray, size_t bit, int *prev_val)
     307                 :            : {
     308                 :            :         k_spinlock_key_t key;
     309                 :            :         int ret;
     310                 :            :         size_t idx, off;
     311                 :            : 
     312         [ #  # ]:          0 :         __ASSERT_NO_MSG(bitarray != NULL);
     313         [ #  # ]:          0 :         __ASSERT_NO_MSG(bitarray->num_bits > 0);
     314                 :            : 
     315                 :          0 :         key = k_spin_lock(&bitarray->lock);
     316                 :            : 
     317         [ #  # ]:          0 :         CHECKIF(prev_val == NULL) {
     318                 :          0 :                 ret = -EINVAL;
     319                 :          0 :                 goto out;
     320                 :            :         }
     321                 :            : 
     322         [ #  # ]:          0 :         if (bit >= bitarray->num_bits) {
     323                 :          0 :                 ret = -EINVAL;
     324                 :          0 :                 goto out;
     325                 :            :         }
     326                 :            : 
     327                 :          0 :         idx = bit / bundle_bitness(bitarray);
     328                 :          0 :         off = bit % bundle_bitness(bitarray);
     329                 :            : 
     330         [ #  # ]:          0 :         if ((bitarray->bundles[idx] & BIT(off)) != 0) {
     331                 :          0 :                 *prev_val = 1;
     332                 :            :         } else {
     333                 :          0 :                 *prev_val = 0;
     334                 :            :         }
     335                 :            : 
     336                 :          0 :         bitarray->bundles[idx] |= BIT(off);
     337                 :            : 
     338                 :          0 :         ret = 0;
     339                 :            : 
     340                 :          0 : out:
     341                 :          0 :         k_spin_unlock(&bitarray->lock, key);
     342                 :          0 :         return ret;
     343                 :            : }
     344                 :            : 
     345                 :          0 : int sys_bitarray_test_and_clear_bit(sys_bitarray_t *bitarray, size_t bit, int *prev_val)
     346                 :            : {
     347                 :            :         k_spinlock_key_t key;
     348                 :            :         int ret;
     349                 :            :         size_t idx, off;
     350                 :            : 
     351         [ #  # ]:          0 :         __ASSERT_NO_MSG(bitarray != NULL);
     352         [ #  # ]:          0 :         __ASSERT_NO_MSG(bitarray->num_bits > 0);
     353                 :            : 
     354                 :          0 :         key = k_spin_lock(&bitarray->lock);
     355                 :            : 
     356         [ #  # ]:          0 :         CHECKIF(prev_val == NULL) {
     357                 :          0 :                 ret = -EINVAL;
     358                 :          0 :                 goto out;
     359                 :            :         }
     360                 :            : 
     361         [ #  # ]:          0 :         if (bit >= bitarray->num_bits) {
     362                 :          0 :                 ret = -EINVAL;
     363                 :          0 :                 goto out;
     364                 :            :         }
     365                 :            : 
     366                 :          0 :         idx = bit / bundle_bitness(bitarray);
     367                 :          0 :         off = bit % bundle_bitness(bitarray);
     368                 :            : 
     369         [ #  # ]:          0 :         if ((bitarray->bundles[idx] & BIT(off)) != 0) {
     370                 :          0 :                 *prev_val = 1;
     371                 :            :         } else {
     372                 :          0 :                 *prev_val = 0;
     373                 :            :         }
     374                 :            : 
     375                 :          0 :         bitarray->bundles[idx] &= ~BIT(off);
     376                 :            : 
     377                 :          0 :         ret = 0;
     378                 :            : 
     379                 :          0 : out:
     380                 :          0 :         k_spin_unlock(&bitarray->lock, key);
     381                 :          0 :         return ret;
     382                 :            : }
     383                 :            : 
     384                 :          0 : int sys_bitarray_alloc(sys_bitarray_t *bitarray, size_t num_bits,
     385                 :            :                        size_t *offset)
     386                 :            : {
     387                 :            :         k_spinlock_key_t key;
     388                 :            :         uint32_t bit_idx;
     389                 :            :         int ret;
     390                 :            :         struct bundle_data bd;
     391                 :            :         size_t off_start, off_end;
     392                 :            :         size_t mismatch;
     393                 :            : 
     394         [ #  # ]:          0 :         __ASSERT_NO_MSG(bitarray != NULL);
     395         [ #  # ]:          0 :         __ASSERT_NO_MSG(bitarray->num_bits > 0);
     396                 :            : 
     397                 :          0 :         key = k_spin_lock(&bitarray->lock);
     398                 :            : 
     399         [ #  # ]:          0 :         CHECKIF(offset == NULL) {
     400                 :          0 :                 ret = -EINVAL;
     401                 :          0 :                 goto out;
     402                 :            :         }
     403                 :            : 
     404   [ #  #  #  # ]:          0 :         if ((num_bits == 0) || (num_bits > bitarray->num_bits)) {
     405                 :          0 :                 ret = -EINVAL;
     406                 :          0 :                 goto out;
     407                 :            :         }
     408                 :            : 
     409                 :          0 :         bit_idx = 0;
     410                 :            : 
     411                 :            :         /* Find the first non-allocated bit by looking at bundles
     412                 :            :          * instead of individual bits.
     413                 :            :          *
     414                 :            :          * On RISC-V 64-bit, it complains about undefined reference to `ffs`.
     415                 :            :          * So don't use this on RISCV64.
     416                 :            :          */
     417         [ #  # ]:          0 :         for (ret = 0; ret < bitarray->num_bundles; ret++) {
     418         [ #  # ]:          0 :                 if (~bitarray->bundles[ret] == 0U) {
     419                 :            :                         /* bundle is all 1s => all allocated, skip */
     420                 :          0 :                         bit_idx += bundle_bitness(bitarray);
     421                 :          0 :                         continue;
     422                 :            :                 }
     423                 :            : 
     424         [ #  # ]:          0 :                 if (bitarray->bundles[ret] != 0U) {
     425                 :            :                         /* Find the first free bit in bundle if not all free */
     426                 :          0 :                         off_start = find_lsb_set(~bitarray->bundles[ret]) - 1;
     427                 :          0 :                         bit_idx += off_start;
     428                 :            :                 }
     429                 :            : 
     430                 :          0 :                 break;
     431                 :            :         }
     432                 :            : 
     433                 :          0 :         off_end = bitarray->num_bits - num_bits;
     434                 :          0 :         ret = -ENOSPC;
     435         [ #  # ]:          0 :         while (bit_idx <= off_end) {
     436         [ #  # ]:          0 :                 if (match_region(bitarray, bit_idx, num_bits, false,
     437                 :            :                                  &bd, &mismatch)) {
     438                 :          0 :                         off_end = bit_idx + num_bits - 1;
     439                 :            : 
     440                 :          0 :                         set_region(bitarray, bit_idx, num_bits, true, &bd);
     441                 :            : 
     442                 :          0 :                         *offset = bit_idx;
     443                 :          0 :                         ret = 0;
     444                 :          0 :                         break;
     445                 :            :                 }
     446                 :            : 
     447                 :            :                 /* Fast-forward to the bit just after
     448                 :            :                  * the mismatched bit.
     449                 :            :                  */
     450                 :          0 :                 bit_idx = mismatch + 1;
     451                 :            :         }
     452                 :            : 
     453                 :          0 : out:
     454                 :          0 :         k_spin_unlock(&bitarray->lock, key);
     455                 :          0 :         return ret;
     456                 :            : }
     457                 :            : 
     458                 :          0 : int sys_bitarray_free(sys_bitarray_t *bitarray, size_t num_bits,
     459                 :            :                       size_t offset)
     460                 :            : {
     461                 :            :         k_spinlock_key_t key;
     462                 :            :         int ret;
     463                 :          0 :         size_t off_end = offset + num_bits - 1;
     464                 :            :         struct bundle_data bd;
     465                 :            : 
     466         [ #  # ]:          0 :         __ASSERT_NO_MSG(bitarray != NULL);
     467         [ #  # ]:          0 :         __ASSERT_NO_MSG(bitarray->num_bits > 0);
     468                 :            : 
     469                 :          0 :         key = k_spin_lock(&bitarray->lock);
     470                 :            : 
     471         [ #  # ]:          0 :         if ((num_bits == 0)
     472         [ #  # ]:          0 :             || (num_bits > bitarray->num_bits)
     473         [ #  # ]:          0 :             || (offset >= bitarray->num_bits)
     474         [ #  # ]:          0 :             || (off_end >= bitarray->num_bits)) {
     475                 :          0 :                 ret = -EINVAL;
     476                 :          0 :                 goto out;
     477                 :            :         }
     478                 :            : 
     479                 :            :         /* Note that we need to make sure the bits in specified region
     480                 :            :          * (offset to offset + num_bits) are all allocated before we clear
     481                 :            :          * them.
     482                 :            :          */
     483         [ #  # ]:          0 :         if (match_region(bitarray, offset, num_bits, true, &bd, NULL)) {
     484                 :          0 :                 set_region(bitarray, offset, num_bits, false, &bd);
     485                 :          0 :                 ret = 0;
     486                 :            :         } else {
     487                 :          0 :                 ret = -EFAULT;
     488                 :            :         }
     489                 :            : 
     490                 :          0 : out:
     491                 :          0 :         k_spin_unlock(&bitarray->lock, key);
     492                 :          0 :         return ret;
     493                 :            : }
     494                 :            : 
     495                 :          0 : static bool is_region_set_clear(sys_bitarray_t *bitarray, size_t num_bits,
     496                 :            :                                 size_t offset, bool to_set)
     497                 :            : {
     498                 :            :         bool ret;
     499                 :            :         struct bundle_data bd;
     500                 :          0 :         size_t off_end = offset + num_bits - 1;
     501                 :          0 :         k_spinlock_key_t key = k_spin_lock(&bitarray->lock);
     502                 :            : 
     503         [ #  # ]:          0 :         __ASSERT_NO_MSG(bitarray != NULL);
     504         [ #  # ]:          0 :         __ASSERT_NO_MSG(bitarray->num_bits > 0);
     505                 :            : 
     506         [ #  # ]:          0 :         if ((num_bits == 0)
     507         [ #  # ]:          0 :             || (num_bits > bitarray->num_bits)
     508         [ #  # ]:          0 :             || (offset >= bitarray->num_bits)
     509         [ #  # ]:          0 :             || (off_end >= bitarray->num_bits)) {
     510                 :          0 :                 ret = false;
     511                 :          0 :                 goto out;
     512                 :            :         }
     513                 :            : 
     514                 :          0 :         ret = match_region(bitarray, offset, num_bits, to_set, &bd, NULL);
     515                 :            : 
     516                 :          0 : out:
     517                 :          0 :         k_spin_unlock(&bitarray->lock, key);
     518                 :          0 :         return ret;
     519                 :            : }
     520                 :            : 
     521                 :          0 : bool sys_bitarray_is_region_set(sys_bitarray_t *bitarray, size_t num_bits,
     522                 :            :                                 size_t offset)
     523                 :            : {
     524                 :          0 :         return is_region_set_clear(bitarray, num_bits, offset, true);
     525                 :            : }
     526                 :            : 
     527                 :          0 : bool sys_bitarray_is_region_cleared(sys_bitarray_t *bitarray, size_t num_bits,
     528                 :            :                                     size_t offset)
     529                 :            : {
     530                 :          0 :         return is_region_set_clear(bitarray, num_bits, offset, false);
     531                 :            : }
     532                 :            : 
     533                 :          0 : static int set_clear_region(sys_bitarray_t *bitarray, size_t num_bits,
     534                 :            :                             size_t offset, bool to_set)
     535                 :            : {
     536                 :            :         int ret;
     537                 :          0 :         size_t off_end = offset + num_bits - 1;
     538                 :          0 :         k_spinlock_key_t key = k_spin_lock(&bitarray->lock);
     539                 :            : 
     540         [ #  # ]:          0 :         __ASSERT_NO_MSG(bitarray != NULL);
     541         [ #  # ]:          0 :         __ASSERT_NO_MSG(bitarray->num_bits > 0);
     542                 :            : 
     543         [ #  # ]:          0 :         if ((num_bits == 0)
     544         [ #  # ]:          0 :             || (num_bits > bitarray->num_bits)
     545         [ #  # ]:          0 :             || (offset >= bitarray->num_bits)
     546         [ #  # ]:          0 :             || (off_end >= bitarray->num_bits)) {
     547                 :          0 :                 ret = -EINVAL;
     548                 :          0 :                 goto out;
     549                 :            :         }
     550                 :            : 
     551                 :          0 :         set_region(bitarray, offset, num_bits, to_set, NULL);
     552                 :          0 :         ret = 0;
     553                 :            : 
     554                 :          0 : out:
     555                 :          0 :         k_spin_unlock(&bitarray->lock, key);
     556                 :          0 :         return ret;
     557                 :            : }
     558                 :            : 
     559                 :          0 : int sys_bitarray_test_and_set_region(sys_bitarray_t *bitarray, size_t num_bits,
     560                 :            :                                      size_t offset, bool to_set)
     561                 :            : {
     562                 :            :         int ret;
     563                 :            :         bool region_clear;
     564                 :            :         struct bundle_data bd;
     565                 :            : 
     566         [ #  # ]:          0 :         __ASSERT_NO_MSG(bitarray != NULL);
     567         [ #  # ]:          0 :         __ASSERT_NO_MSG(bitarray->num_bits > 0);
     568                 :            : 
     569                 :          0 :         size_t off_end = offset + num_bits - 1;
     570                 :          0 :         k_spinlock_key_t key = k_spin_lock(&bitarray->lock);
     571                 :            : 
     572                 :            : 
     573         [ #  # ]:          0 :         if ((num_bits == 0)
     574         [ #  # ]:          0 :             || (num_bits > bitarray->num_bits)
     575         [ #  # ]:          0 :             || (offset >= bitarray->num_bits)
     576         [ #  # ]:          0 :             || (off_end >= bitarray->num_bits)) {
     577                 :          0 :                 ret = -EINVAL;
     578                 :          0 :                 goto out;
     579                 :            :         }
     580                 :            : 
     581                 :          0 :         region_clear = match_region(bitarray, offset, num_bits, !to_set, &bd, NULL);
     582         [ #  # ]:          0 :         if (region_clear) {
     583                 :          0 :                 set_region(bitarray, offset, num_bits, to_set, &bd);
     584                 :          0 :                 ret = 0;
     585                 :            :         } else {
     586                 :          0 :                 ret = -EEXIST;
     587                 :            :         }
     588                 :            : 
     589                 :          0 : out:
     590                 :          0 :         k_spin_unlock(&bitarray->lock, key);
     591                 :          0 :         return ret;
     592                 :            : }
     593                 :            : 
     594                 :          0 : int sys_bitarray_set_region(sys_bitarray_t *bitarray, size_t num_bits,
     595                 :            :                             size_t offset)
     596                 :            : {
     597                 :          0 :         return set_clear_region(bitarray, num_bits, offset, true);
     598                 :            : }
     599                 :            : 
     600                 :          0 : int sys_bitarray_clear_region(sys_bitarray_t *bitarray, size_t num_bits,
     601                 :            :                               size_t offset)
     602                 :            : {
     603                 :          0 :         return set_clear_region(bitarray, num_bits, offset, false);
     604                 :            : }

Generated by: LCOV version 1.14