Files
drivers_framework/utils/src/hdf_object_alloc.c
YOUR_NAME 3016511bde clear the warings of reviewbot
Signed-off-by: YOUR_NAME <guodongqi2@huawei.com>
2021-10-15 09:34:32 +08:00

190 lines
5.9 KiB
C

/*
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#include "hdf_object_alloc.h"
#include "hdf_slist.h"
#include "osal_mutex.h"
struct HdfChunkLink {
uint32_t buffSize;
uint8_t *buffer;
};
struct HdfObjectNode {
struct HdfSListNode entry;
uint32_t chunkCount;
uint32_t freeCount;
uint32_t chunkSize;
struct HdfChunkLink **chunkStack;
};
struct HdfObjectAlloc {
struct HdfSList nodes;
struct OsalMutex mutex;
bool isConstructed;
};
static const unsigned int ALIGN_MASK = 3;
#define ALIGN4(x) (uint32_t)(((uintptr_t)(x) + ALIGN_MASK) & (~ALIGN_MASK))
#define OBJECT_NODE_SIZE sizeof(struct ObjectNode)
#define OBJECT_CHUNK_COOKIE_SIZE (sizeof(struct ChunkLink) + sizeof(void *))
void HdfObjectAllocConstruct(struct HdfObjectAlloc *alloc)
{
HdfSListInit(&alloc->nodes);
OsalMutexInit(&alloc->mutex);
alloc->isConstructed = true;
}
struct HdfObjectAlloc *HdfObjectAllocGetInstance()
{
static struct HdfObjectAlloc instance = { 0 };
if (!instance.isConstructed) {
HdfObjectAllocConstruct(&instance);
}
return &instance;
}
struct HdfObjectNode *HdfObjectAllocFindSuitableChunk(
struct HdfObjectAlloc *alloc, size_t size)
{
struct HdfSListIterator it;
struct HdfObjectNode *bestFitNode = NULL;
struct HdfObjectNode *objectNode = NULL;
HdfSListIteratorInit(&it, &alloc->nodes);
while (HdfSListIteratorHasNext(&it)) {
objectNode = (struct HdfObjectNode *)HdfSListIteratorNext(&it);
if (size == objectNode->chunkSize) {
bestFitNode = objectNode;
break;
} else if (size < objectNode->chunkSize) {
bestFitNode = objectNode;
}
}
return bestFitNode;
}
static void HdfObjectAllocPushObjectNode(
struct HdfObjectAlloc *alloc, struct HdfObjectNode *node)
{
struct HdfSListIterator it;
struct HdfObjectNode *objectNode = NULL;
HdfSListIteratorInit(&it, &alloc->nodes);
while (HdfSListIteratorHasNext(&it)) {
objectNode = (struct HdfObjectNode *)HdfSListIteratorNext(&it);
if (node->chunkSize >= objectNode->chunkSize) {
break;
}
}
HdfSListIteratorInsert(&it, &node->entry);
}
static void HdfObjectAllocPreloadChunk(
void *chunkBuf, uint32_t buffSize, uint32_t chunkSize)
{
struct HdfObjectAlloc *allocator = HdfObjectAllocGetInstance();
if (buffSize > OBJECT_NODE_SIZE) {
uint32_t idx;
struct ChunkLink *chunkLink;
struct ObjectNode *node;
uint32_t alignedSize = ALIGN4(chunkSize);
uint32_t alignedBufSize = ALIGN4(buffSize);
uint32_t blockSize = alignedSize + sizeof(struct ChunkLink);
uint8_t *alignedBuff = (uint8_t *)(uintptr_t)ALIGN4(chunkBuf);
node = (struct ObjectNode *)(alignedBuff + alignedBufSize - OBJECT_NODE_SIZE);
node->freeCount = 0;
node->chunkSize = alignedSize;
node->chunkCount = ((uint8_t *)node - alignedBuff) / (blockSize + sizeof(void *));
node->chunkStack = (struct ChunkLink **)(alignedBuff + node->chunkCount * blockSize);
for (idx = 0; idx < node->chunkCount; idx++) {
chunkLink = (struct ChunkLink *)&alignedBuff[idx * blockSize];
chunkLink->buffSize = node->chunkSize;
node->chunkStack[node->freeCount++] = chunkLink;
chunkLink->buffer = (uint8_t *)(chunkLink + 1);
}
HdfObjectAllocPushObjectNode(allocator, node);
}
}
void HdfObjectAllocLoadConfigs(const struct HdfObjectPoolConfig *configs)
{
uint32_t idx;
char *chunkBuffBegin = configs->buffer;
char *chunkBuffEnd = configs->buffer + configs->bufferSize;
for (idx = 0; (idx < configs->numChunks) && (chunkBuffBegin < chunkBuffEnd); idx++) {
const struct ObjectChunkConfig *chunkConfig = &configs->chunks[idx];
size_t chunkBufSize = OBJECT_NODE_SIZE + \
(OBJECT_CHUNK_COOKIE_SIZE + chunkConfig->chunkSize) * chunkConfig->chunkCount;
if (chunkBuffBegin + chunkBufSize <= chunkBuffEnd) {
HdfObjectAllocPreloadChunk(chunkBuffBegin, chunkBufSize, chunkConfig->chunkSize);
}
chunkBuffBegin += chunkBufSize;
}
}
void HdfObjectAllocInit()
{
const struct HdfObjectPoolConfig *config = HdfObjectAllocGetConfig();
if (config != NULL) {
HdfObjectAllocLoadConfigs(config);
}
}
void *HdfObjectAllocAlloc(size_t size)
{
struct HdfChunkLink *chunkLink = NULL;
struct HdfObjectNode *objectNode = NULL;
struct HdfObjectAlloc *allocator = HdfObjectAllocGetInstance();
OsalMutexLock(&allocator->mutex);
objectNode = HdfObjectAllocFindSuitableChunk(allocator, size);
if ((objectNode != NULL) && (objectNode->freeCount == 0)) {
goto finished;
}
if (objectNode->freeCount > objectNode->chunkCount) {
if (objectNode->freeCount > objectNode->chunkCount) {
}
}
chunkLink = (struct ChunkLink *)objectNode->chunkStack[--objectNode->freeCount];
finished:
OsalMutexUnlock(&allocator->mutex);
return chunkLink ? chunkLink->buffer : NULL;
}
void HdfObjectAllocFree(void *object)
{
struct HdfChunkLink *chunkLink = container_of(void, object, struct ChunkLink, buffer);
struct HdfObjectNode *objectNode = NULL;
struct HdfObjectAlloc *allocator = HdfObjectAllocGetInstance();
OsalMutexLock(&allocator->mutex);
objectNode = HdfObjectAllocFindSuitableChunk(allocator, chunkLink->buffSize);
if (objectNode != NULL) {
objectNode->chunkStack[objectNode->freeCount++] = chunkLink;
if (objectNode->freeCount > objectNode->chunkCount) {
HDF_LOGE("exception: count,free:%d,total %d", objectNode->freeCount, objectNode->chunkCount);
}
}
OsalMutexUnlock(&allocator->mutex);
}