106 lines
3.0 KiB
C
106 lines
3.0 KiB
C
/*
|
|
* Copyright (C) 2016 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <atomicBitset.h>
|
|
#include <stdio.h>
|
|
#include <heap.h>
|
|
#include <slab.h>
|
|
|
|
struct SlabAllocator {
|
|
|
|
uint32_t itemSz;
|
|
uint8_t *dataChunks;
|
|
struct AtomicBitset bitset[0];
|
|
};
|
|
|
|
struct SlabAllocator* slabAllocatorNew(uint32_t itemSz, uint32_t itemAlign, uint32_t numItems)
|
|
{
|
|
struct SlabAllocator *allocator;
|
|
uint32_t bitsetSz, dataSz;
|
|
|
|
/* calcualte size */
|
|
bitsetSz = ATOMIC_BITSET_SZ(numItems);
|
|
bitsetSz = ((bitsetSz + itemAlign - 1) / itemAlign) * itemAlign;
|
|
|
|
itemSz = ((itemSz + itemAlign - 1) / itemAlign) * itemAlign;
|
|
dataSz = itemSz * numItems;
|
|
|
|
/* allocate & init*/
|
|
allocator = (struct SlabAllocator*)heapAlloc(sizeof(struct SlabAllocator) + bitsetSz + dataSz);
|
|
if (allocator) {
|
|
allocator->itemSz = itemSz;
|
|
allocator->dataChunks = ((uint8_t*)allocator->bitset) + bitsetSz;
|
|
atomicBitsetInit(allocator->bitset, numItems);
|
|
}
|
|
|
|
return allocator;
|
|
}
|
|
|
|
void slabAllocatorDestroy(struct SlabAllocator *allocator)
|
|
{
|
|
heapFree(allocator);
|
|
}
|
|
|
|
void* slabAllocatorAlloc(struct SlabAllocator *allocator)
|
|
{
|
|
int32_t itemIdx = atomicBitsetFindClearAndSet(allocator->bitset);
|
|
|
|
if (itemIdx < 0)
|
|
return NULL;
|
|
|
|
return allocator->dataChunks + allocator->itemSz * itemIdx;
|
|
}
|
|
|
|
void slabAllocatorFree(struct SlabAllocator *allocator, void* ptrP)
|
|
{
|
|
uint8_t *ptr = (uint8_t*)ptrP;
|
|
uint32_t itemOffset = ptr - allocator->dataChunks;
|
|
uint32_t itemIdx = itemOffset / allocator->itemSz;
|
|
|
|
//check for invalid inputs
|
|
if ((itemOffset % allocator->itemSz) || (itemIdx >= atomicBitsetGetNumBits(allocator->bitset)) || !atomicBitsetGetBit(allocator->bitset, itemIdx))
|
|
return;
|
|
|
|
atomicBitsetClearBit(allocator->bitset, itemIdx);
|
|
}
|
|
|
|
void* slabAllocatorGetNth(struct SlabAllocator *allocator, uint32_t idx)
|
|
{
|
|
if (!atomicBitsetGetBit(allocator->bitset, idx))
|
|
return NULL;
|
|
|
|
return allocator->dataChunks + allocator->itemSz * idx;
|
|
}
|
|
|
|
uint32_t slabAllocatorGetIndex(struct SlabAllocator *allocator, void* ptrP)
|
|
{
|
|
uint8_t *ptr = (uint8_t*)ptrP;
|
|
uint32_t itemOffset = ptr - allocator->dataChunks;
|
|
uint32_t itemIdx = itemOffset / allocator->itemSz;
|
|
|
|
if ((itemOffset % allocator->itemSz) || (itemIdx >= atomicBitsetGetNumBits(allocator->bitset)) || !atomicBitsetGetBit(allocator->bitset, itemIdx))
|
|
return -1;
|
|
|
|
return itemIdx;
|
|
}
|
|
|
|
uint32_t slabAllocatorGetNumItems(struct SlabAllocator *allocator)
|
|
{
|
|
return atomicBitsetGetNumBits(allocator->bitset);
|
|
}
|
|
|
|
|