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