LCOV - code coverage report
Current view: top level - lib/support - Pool.cpp (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 66 78 84.6 %
Date: 2024-02-15 08:20:41 Functions: 7 9 77.8 %

          Line data    Source code
       1             : /*
       2             :  *
       3             :  *    Copyright (c) 2020 Project CHIP Authors
       4             :  *    Copyright (c) 2013 Nest Labs, Inc.
       5             :  *    All rights reserved.
       6             :  *
       7             :  *    Licensed under the Apache License, Version 2.0 (the "License");
       8             :  *    you may not use this file except in compliance with the License.
       9             :  *    You may obtain a copy of the License at
      10             :  *
      11             :  *        http://www.apache.org/licenses/LICENSE-2.0
      12             :  *
      13             :  *    Unless required by applicable law or agreed to in writing, software
      14             :  *    distributed under the License is distributed on an "AS IS" BASIS,
      15             :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      16             :  *    See the License for the specific language governing permissions and
      17             :  *    limitations under the License.
      18             :  */
      19             : 
      20             : #include <lib/support/CodeUtils.h>
      21             : #include <lib/support/Pool.h>
      22             : 
      23             : namespace chip {
      24             : 
      25             : #if CHIP_SYSTEM_CONFIG_POOL_USE_HEAP
      26             : 
      27             : bool HeapObjectPoolExitHandling::sIgnoringLeaksOnExit   = false;
      28             : bool HeapObjectPoolExitHandling::sExitHandlerRegistered = false;
      29             : 
      30           0 : void HeapObjectPoolExitHandling::IgnoreLeaksOnExit()
      31             : {
      32           0 :     if (sExitHandlerRegistered)
      33             :     {
      34           0 :         return;
      35             :     }
      36             : 
      37           0 :     int ret = atexit(ExitHandler);
      38           0 :     if (ret != 0)
      39             :     {
      40           0 :         ChipLogError(Controller, "IgnoreLeaksOnExit: atexit failed: %d\n", ret);
      41             :     }
      42           0 :     sExitHandlerRegistered = true;
      43             : }
      44             : 
      45           0 : void HeapObjectPoolExitHandling::ExitHandler()
      46             : {
      47           0 :     sIgnoringLeaksOnExit = true;
      48           0 : }
      49             : 
      50             : #endif // CHIP_SYSTEM_CONFIG_POOL_USE_HEAP
      51             : 
      52             : namespace internal {
      53             : 
      54          80 : StaticAllocatorBitmap::StaticAllocatorBitmap(void * storage, std::atomic<tBitChunkType> * usage, size_t capacity,
      55          80 :                                              size_t elementSize) :
      56             :     StaticAllocatorBase(capacity),
      57          80 :     mElements(storage), mElementSize(elementSize), mUsage(usage)
      58             : {
      59         152 :     for (size_t word = 0; word * kBitChunkSize < Capacity(); ++word)
      60             :     {
      61          72 :         mUsage[word].store(0);
      62             :     }
      63          80 : }
      64             : 
      65         956 : void * StaticAllocatorBitmap::Allocate()
      66             : {
      67        1212 :     for (size_t word = 0; word * kBitChunkSize < Capacity(); ++word)
      68             :     {
      69        1208 :         auto & usage = mUsage[word];
      70        1208 :         auto value   = usage.load(std::memory_order_relaxed);
      71       38207 :         for (size_t offset = 0; offset < kBitChunkSize && offset + word * kBitChunkSize < Capacity(); ++offset)
      72             :         {
      73       37951 :             if ((value & (kBit1 << offset)) == 0)
      74             :             {
      75        1904 :                 if (usage.compare_exchange_strong(value, value | (kBit1 << offset)))
      76             :                 {
      77         952 :                     IncreaseUsage();
      78         952 :                     return At(word * kBitChunkSize + offset);
      79             :                 }
      80             : 
      81           0 :                 value = usage.load(std::memory_order_relaxed); // if there is a race, update new usage
      82             :             }
      83             :         }
      84             :     }
      85           4 :     return nullptr;
      86             : }
      87             : 
      88         952 : void StaticAllocatorBitmap::Deallocate(void * element)
      89             : {
      90         952 :     size_t index  = IndexOf(element);
      91         952 :     size_t word   = index / kBitChunkSize;
      92         952 :     size_t offset = index - (word * kBitChunkSize);
      93             : 
      94             :     // ensure the element is in the pool
      95         952 :     VerifyOrDie(index < Capacity());
      96             : 
      97         952 :     auto value = mUsage[word].fetch_and(~(kBit1 << offset));
      98         952 :     VerifyOrDie((value & (kBit1 << offset)) != 0); // assert fail when free an unused slot
      99         952 :     DecreaseUsage();
     100         952 : }
     101             : 
     102         952 : size_t StaticAllocatorBitmap::IndexOf(void * element)
     103             : {
     104         952 :     std::ptrdiff_t diff = static_cast<uint8_t *>(element) - static_cast<uint8_t *>(mElements);
     105         952 :     VerifyOrDie(diff >= 0);
     106         952 :     VerifyOrDie(static_cast<size_t>(diff) % mElementSize == 0);
     107         952 :     auto index = static_cast<size_t>(diff) / mElementSize;
     108         952 :     VerifyOrDie(index < Capacity());
     109         952 :     return index;
     110             : }
     111             : 
     112        3904 : Loop StaticAllocatorBitmap::ForEachActiveObjectInner(void * context, Lambda lambda)
     113             : {
     114        8508 :     for (size_t word = 0; word * kBitChunkSize < Capacity(); ++word)
     115             :     {
     116        4969 :         auto & usage = mUsage[word];
     117        4969 :         auto value   = usage.load(std::memory_order_relaxed);
     118      139431 :         for (size_t offset = 0; offset < kBitChunkSize && offset + word * kBitChunkSize < Capacity(); ++offset)
     119             :         {
     120      134827 :             if ((value & (kBit1 << offset)) != 0)
     121             :             {
     122       59346 :                 if (lambda(context, At(word * kBitChunkSize + offset)) == Loop::Break)
     123         365 :                     return Loop::Break;
     124             :             }
     125             :         }
     126             :     }
     127        3539 :     return Loop::Finish;
     128             : }
     129             : 
     130             : #if CHIP_SYSTEM_CONFIG_POOL_USE_HEAP
     131             : 
     132     4283102 : HeapObjectListNode * HeapObjectList::FindNode(void * object) const
     133             : {
     134    12237735 :     for (HeapObjectListNode * p = mNext; p != this; p = p->mNext)
     135             :     {
     136    12237735 :         if (p->mObject == object)
     137             :         {
     138     4283102 :             return p;
     139             :         }
     140             :     }
     141           0 :     return nullptr;
     142             : }
     143             : 
     144      251813 : Loop HeapObjectList::ForEachNode(void * context, Lambda lambda)
     145             : {
     146      251813 :     ++mIterationDepth;
     147      251813 :     Loop result            = Loop::Finish;
     148      251813 :     HeapObjectListNode * p = mNext;
     149     3903474 :     while (p != this)
     150             :     {
     151     3681661 :         if (p->mObject != nullptr)
     152             :         {
     153     3673602 :             if (lambda(context, p->mObject) == Loop::Break)
     154             :             {
     155       30000 :                 result = Loop::Break;
     156       30000 :                 break;
     157             :             }
     158             :         }
     159     3651661 :         p = p->mNext;
     160             :     }
     161      251813 :     --mIterationDepth;
     162      251813 :     if (mIterationDepth == 0 && mHaveDeferredNodeRemovals)
     163             :     {
     164             :         // Remove nodes for released objects.
     165       11267 :         p = mNext;
     166       68541 :         while (p != this)
     167             :         {
     168       57274 :             HeapObjectListNode * next = p->mNext;
     169       57274 :             if (p->mObject == nullptr)
     170             :             {
     171       12658 :                 p->Remove();
     172       12658 :                 Platform::Delete(p);
     173             :             }
     174       57274 :             p = next;
     175             :         }
     176             : 
     177       11267 :         mHaveDeferredNodeRemovals = false;
     178             :     }
     179      251813 :     return result;
     180             : }
     181             : 
     182             : #endif // CHIP_SYSTEM_CONFIG_POOL_USE_HEAP
     183             : 
     184             : } // namespace internal
     185             : } // namespace chip

Generated by: LCOV version 1.14