doubao_chat/lib/net/libduer-device/framework/utils/lightduer_bitmap.c

277 lines
7.8 KiB
C

/**
* Copyright (2017) Baidu Inc. All rights reserved.
*
* 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.
*/
// Author: Zhang Leliang(zhangleliang@baidu.com)
//
// Description: bitmap cache for fix-sized objects.
#include "stdlib.h"
#include "lightduer_bitmap.h"
#include "lightduer_log.h"
#include "lightduer_memory.h"
static duer_mutex_t s_bitmap_lock = NULL;
int dump_bitmap(bitmap_objects_t *bop, const char *tag)
{
DUER_LOGI("=========%s", tag);
DUER_LOGI("num_of_objs:%d, num_of_bitmaps:%d\n", bop->num_of_objs, bop->num_of_bitmaps);
for (int i = 0; i < bop->num_of_bitmaps; ++i) {
DUER_LOGI("%x ", bop->bitmaps[i]);
}
DUER_LOGI("\n");
DUER_LOGI("=========%s", tag);
return 0;
}
int clear_index(bitmap_objects_t *bop, int index)
{
if (index >= bop->num_of_objs) {
DUER_LOGE("index(%d) bigger than max(%d)", index, bop->num_of_objs);
return -1;
}
//int i_of_bitmap = index / (sizeof(unisgned char) * 8);
//int offset_of_bitmap = index % (sizeof(unsigned char) * 8);
int i_of_bitmap = index >> 3;
int offset_of_bitmap = index & 0x07;
unsigned char mask = 0x1 << offset_of_bitmap;
//printf("test index:%d, i:%d, offset:%d, 0x%x\n", index, i_of_bitmap, offset_of_bitmap, mask);
if (bop->bitmaps[i_of_bitmap] & mask) {
bop->bitmaps[i_of_bitmap] &= ~mask;
return 0;
} else {
DUER_LOGE("index(%d) already clear!", index);
return -1;
}
}
int set_index(bitmap_objects_t *bop, int index)
{
if (index >= bop->num_of_objs) {
DUER_LOGE("index(%d) bigger than max(%d)", index, bop->num_of_objs);
return -1;
}
//int i_of_bitmap = index / (sizeof(unsigned char) * 8);
//int offset_of_bitmap = index % (sizeof(unsigned char) * 8);
int i_of_bitmap = index >> 3;
int offset_of_bitmap = index & 0x07;
unsigned char mask = 0x1 << offset_of_bitmap;
//printf("test index:%d, i:%d, offset:%d, 0x%x\n", index, i_of_bitmap, offset_of_bitmap, mask);
if (!(bop->bitmaps[i_of_bitmap] & mask)) {
bop->bitmaps[i_of_bitmap] |= mask;
return 0;
} else {
DUER_LOGE("index(%d) already set!", index);
return -1;
}
}
int first_free_index(bitmap_objects_t *bop)
{
int index = -1;
int current_index = 0;
int found = 0;
for (int i = 0; i < bop->num_of_bitmaps; ++i) {
if (found || current_index >= bop->num_of_objs) {
break;
}
unsigned char b = bop->bitmaps[i];
//printf("test, %x, current_index:%d \n", b, current_index);
for (int j = 0; j < sizeof(unsigned char) * 8; ++j) {
if (!(b & 0x1)) {
found = 1;
break;
}
b >>= 1;
if (++current_index >= bop->num_of_objs) {
break;
}
}
}
if (current_index < bop->num_of_objs) {
if (set_index(bop, current_index) < 0) {//Note: whether it is perfect to set here
return index;
}
index = current_index;
}
return index;
}
int first_set_index(bitmap_objects_t *bop)
{
int index = -1;
int current_index = 0;
int found = 0;
for (int i = 0; i < bop->num_of_bitmaps; ++i) {
if (found || current_index >= bop->num_of_objs) {
break;
}
unsigned char b = bop->bitmaps[i];
for (int j = 0; j < sizeof(unsigned char) * 8; ++j) {
if ((b & 0x1)) {
found = 1;
break;
}
b >>= 1;
if (++current_index >= bop->num_of_objs) {
break;
}
}
}
if (current_index < bop->num_of_objs) {
index = current_index;
}
return index;
}
int init_bitmap(int object_num, bitmap_objects_t *bop, int element_size)
{
if (bop == NULL || object_num <= 0) {
DUER_LOGW("invalid params!");
return -1;
}
if (uninit_bitmap(bop) != 0) {
DUER_LOGW("invalid status!");
return -1;
}
int num_of_objs_in_one_type = sizeof(unsigned char) * 8;
int bitmap_num = (object_num + num_of_objs_in_one_type - 1) / (num_of_objs_in_one_type);
int all_size = object_num * element_size + bitmap_num * sizeof(unsigned char);
DUER_LOGI("test obj_num:%d, bitmap_num:%d,all_size:%d, nooiot:%d",
object_num, bitmap_num, all_size, num_of_objs_in_one_type);
bop->num_of_objs = object_num;
bop->num_of_bitmaps = bitmap_num;
bop->bitmap_lock = NULL; // not used now
bop->element_size = element_size;
if (!s_bitmap_lock) {
s_bitmap_lock = duer_mutex_create(); // maybe fail, beccause the mutex not initialized.
}
if (!bop->bitmaps) {
bop->bitmaps = DUER_CALLOC(bitmap_num * sizeof(unsigned char), 1);
}
if (!bop->objects) {
bop->objects = DUER_MALLOC(object_num * element_size);
}
return 0;
}
int uninit_bitmap(bitmap_objects_t *bop)
{
//check if all bitmap is free
if (bop->bitmaps) {
int f_s_index = first_set_index(bop);
if (f_s_index != -1) {
DUER_LOGE("the first set index is %d!", f_s_index);
return -1;
}
}
bop->num_of_objs = 0;
bop->num_of_bitmaps = 0;
// NOTE, keep the mutex
// if (s_bitmap_lock) {
// duer_mutex_destroy(s_bitmap_lock);
// s_bitmap_lock = NULL;
// }
if (bop->bitmaps) {
DUER_FREE(bop->bitmaps);
bop->bitmaps = NULL;
}
if (bop->objects) {
DUER_FREE(bop->objects);
bop->objects = NULL;
}
return 0;
}
void *alloc_obj(bitmap_objects_t *bop)
{
if (!s_bitmap_lock) {
//Note if null will create because the mutex maybe craete fail in init func
s_bitmap_lock = duer_mutex_create();
if (!s_bitmap_lock) {
DUER_LOGE("mutex is not initialized!");
return NULL;
}
}
// if (!s_bitmap_lock) {
// printf("mutex create fail!\n");
// }
// int r = 0;
duer_mutex_lock(s_bitmap_lock);
// if (r != 0) {
// printf("fail to lock\n");
// }
// dump_bitmap(&bitmap_objects, "before alloc");
int index = first_free_index(bop);
duer_mutex_unlock(s_bitmap_lock);
if (index >= 0) {
// dump_bitmap(&bitmap_objects, "after alloc");
void *obj = (char *)bop->objects + (bop->element_size * index);
return obj;
}
return NULL;
}
int free_obj(bitmap_objects_t *bop, void *obj)
{
if (obj < bop->objects || (char *)obj >= ((char *)bop->objects + bop->num_of_objs * bop->element_size)) {
//DUER_LOGI("obj not in the bitmap buffer:%p", obj); // maybe print too much
return -2;
}
if (!s_bitmap_lock) {
DUER_LOGE("mutex is not initialized!");
return -1;
}
int index = ((char *)obj - (char *)bop->objects) / bop->element_size;
//printf("index:%d, obj:%p, base:%p\n", index, obj, bop->objects);
// int r = 0;
duer_mutex_lock(s_bitmap_lock);
//dump_bitmap(&bitmap_objects, "before free");
// if (r != 0) {
// printf("fail to lock\n");
// }
int r = clear_index(bop, index);
//dump_bitmap(&bitmap_objects, "after free");
duer_mutex_unlock(s_bitmap_lock);
return r;
}
int lock_bitmap(bitmap_objects_t *bop)
{
return duer_mutex_lock(s_bitmap_lock);
}
int unlock_bitmap(bitmap_objects_t *bop)
{
return duer_mutex_unlock(s_bitmap_lock);
}