Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <atomicBitset.h>
     18 #include <stdio.h>
     19 #include <heap.h>
     20 #include <slab.h>
     21 
     22 struct SlabAllocator {
     23 
     24     uint32_t itemSz;
     25     uint8_t *dataChunks;
     26     struct AtomicBitset bitset[0];
     27 };
     28 
     29 struct SlabAllocator* slabAllocatorNew(uint32_t itemSz, uint32_t itemAlign, uint32_t numItems)
     30 {
     31     struct SlabAllocator *allocator;
     32     uint32_t bitsetSz, dataSz;
     33 
     34     /* calcualte size */
     35     bitsetSz = ATOMIC_BITSET_SZ(numItems);
     36     bitsetSz = ((bitsetSz + itemAlign - 1) / itemAlign) * itemAlign;
     37 
     38     itemSz = ((itemSz + itemAlign - 1) / itemAlign) * itemAlign;
     39     dataSz = itemSz * numItems;
     40 
     41     /* allocate & init*/
     42     allocator = (struct SlabAllocator*)heapAlloc(sizeof(struct SlabAllocator) + bitsetSz + dataSz);
     43     if (allocator) {
     44         allocator->itemSz = itemSz;
     45         allocator->dataChunks = ((uint8_t*)allocator->bitset) + bitsetSz;
     46         atomicBitsetInit(allocator->bitset, numItems);
     47     }
     48 
     49     return allocator;
     50 }
     51 
     52 void slabAllocatorDestroy(struct SlabAllocator *allocator)
     53 {
     54     heapFree(allocator);
     55 }
     56 
     57 void* slabAllocatorAlloc(struct SlabAllocator *allocator)
     58 {
     59     int32_t itemIdx = atomicBitsetFindClearAndSet(allocator->bitset);
     60 
     61     if (itemIdx < 0)
     62         return NULL;
     63 
     64     return allocator->dataChunks + allocator->itemSz * itemIdx;
     65 }
     66 
     67 void slabAllocatorFree(struct SlabAllocator *allocator, void* ptrP)
     68 {
     69     uint8_t *ptr = (uint8_t*)ptrP;
     70     uint32_t itemOffset = ptr - allocator->dataChunks;
     71     uint32_t itemIdx = itemOffset / allocator->itemSz;
     72 
     73     //check for invalid inputs
     74     if ((itemOffset % allocator->itemSz) || (itemIdx >= atomicBitsetGetNumBits(allocator->bitset)) || !atomicBitsetGetBit(allocator->bitset, itemIdx))
     75         return;
     76 
     77     atomicBitsetClearBit(allocator->bitset, itemIdx);
     78 }
     79 
     80 void* slabAllocatorGetNth(struct SlabAllocator *allocator, uint32_t idx)
     81 {
     82     if (!atomicBitsetGetBit(allocator->bitset, idx))
     83         return NULL;
     84 
     85     return allocator->dataChunks + allocator->itemSz * idx;
     86 }
     87 
     88 uint32_t slabAllocatorGetIndex(struct SlabAllocator *allocator, void* ptrP)
     89 {
     90     uint8_t *ptr = (uint8_t*)ptrP;
     91     uint32_t itemOffset = ptr - allocator->dataChunks;
     92     uint32_t itemIdx = itemOffset / allocator->itemSz;
     93 
     94     if ((itemOffset % allocator->itemSz) || (itemIdx >= atomicBitsetGetNumBits(allocator->bitset)) || !atomicBitsetGetBit(allocator->bitset, itemIdx))
     95         return -1;
     96 
     97     return itemIdx;
     98 }
     99 
    100 uint32_t slabAllocatorGetNumItems(struct SlabAllocator *allocator)
    101 {
    102     return atomicBitsetGetNumBits(allocator->bitset);
    103 }
    104 
    105 
    106