277 lines
7.8 KiB
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);
|
|
}
|