Patch add idr (#56)

* 增加了idr模块

* 增加了IDR模块,并尝试覆盖上一个错误版本.

* 增加了IDR模块

* 修改了test-idr.c文件

* 进一步完善函数注释

* 更新idr文档同时修改了test-idr的错误


* 将lz4库改为使用系统的clz函数

* idr和test-idr O1

* bugfix: 修复测试用例中的移位问题

* 修正问题

Signed-off-by: guanjinquan <1666320330@qq.com>
Co-authored-by: fslongjin <longjin@RinGoTek.cn>
This commit is contained in:
guanjinquan
2022-10-23 16:07:28 +08:00
committed by GitHub
parent d328bfce6b
commit d53ddde95d
8 changed files with 886 additions and 175 deletions

View File

@ -1,8 +1,16 @@
#pragma GCC push_options
#pragma GCC optimize("O1")
#include <common/errno.h>
#include <common/spinlock.h>
#if ARCH(I386) || ARCH(X86_64)
#include <arch/x86_64/math/bitcount.h>
#else
#error Arch not supported.
#endif
/**
* idr: 基于radix-tree的ID-pointer的数据结构
* 主要功能:
@ -33,17 +41,17 @@
#define MAX_ID_MASK (MAX_ID_BIT - 1)
// IDR可能最大的层次 以及 IDR预分配空间的最大限制
#define MAX_LEVEL (MAX_ID_SHIFT + IDR_BITS - 1) / IDR_BITS
#define MAX_LEVEL ((MAX_ID_SHIFT + IDR_BITS - 1) / IDR_BITS)
#define IDR_FREE_MAX (MAX_LEVEL << 1)
// 给定layer, 计算完全64叉树的大小
#define TREE_SIZE(layer) ((layer >= 0) ? (1ull << ((layer + 1) * IDR_BITS)) : 1)
// 计算最后(最低位)一个1的位置 (注意使用64位的版本)
#define __lowbit_id(x) ((x) ? (__builtin_ctzll(x)) : -1)
#define __lowbit_id(x) ((x) ? (__ctzll(x)) : -1)
// 计算最前(最高位)一个1的位置 (注意使用64位的版本)
#define __mostbit_id(x) ((x) ? (__builtin_clzll(x)) : -1)
#define __mostbit_id(x) ((x) ? (63 - __clzll(x)) : -1)
// radix-tree 节点定义
struct idr_layer
@ -61,14 +69,11 @@ struct idr
struct idr_layer *free_list;
int id_free_cnt;
spinlock_t lock;
};
}__attribute__((aligned(8)));
#define DECLARE_IDR(name) \
struct idr name = {0}; \
name.top = (NULL); \
name.free_list = (NULL); \
name.id_free_cnt = (0); \
spin_init(&name.lock);
idr_init(&(name));
#define DECLARE_IDR_LAYER(name) \
struct idr_layer name = {0}; \
@ -77,17 +82,43 @@ struct idr
/**
* 对外函数声明
**/
int idr_pre_get(struct idr *idp, gfp_t gfp_mask);
int idr_get_new(struct idr *idp, void *ptr, int *id);
void idr_remove(struct idr *idp, int id);
int idr_preload(struct idr *idp, gfp_t gfp_mask);
int idr_alloc(struct idr *idp, void *ptr, int *id);
void *idr_remove(struct idr *idp, int id);
void idr_remove_all(struct idr *idp);
void idr_destroy(struct idr *idp);
void *idr_find(struct idr *idp, int id);
void *idr_find_next(struct idr *idp, int start_id);
void *idr_find_next_getid(struct idr *idp, int start_id, int *nextid);
void *idr_find_next_getid(struct idr *idp, int64_t start_id, int *nextid);
int idr_replace_get_old(struct idr *idp, void *ptr, int id, void **oldptr);
int idr_replace(struct idr *idp, void *ptr, int id);
void idr_init(struct idr *idp);
bool idr_empty(struct idr *idp);
bool idr_count(struct idr *idp, int id);
/**
* 对外宏遍历idr两种方式
* 1. 从第一个元素开始遍历
* 2. 从某一个id开始遍历
*/
/**
* @brief 第一种遍历方式: 从第一个元素开始遍历
* @param idp idr指针
* @param id 遍历的id你不需要初始化这个id因为它每一次都是从最小已分配的id开始遍历
* @param ptr 数据指针(entry),你不需要初始化这个指针
*/
#define for_each_idr_entry(idp, id, ptr) \
for (id = -1, ptr = idr_find_next_getid(idp, id, &id); ptr != NULL || !idr_count(idp, id); ptr = idr_find_next_getid(idp, id, &id))
/**
* @brief 第二种遍历方式: 从某一个id开始遍历
* @param idp idr指针
* @param id 遍历的id你需要初始化这个id(请你设置为你要从哪一个id开始遍历遍历过程将会包括这个id)
* @param ptr 数据指针(entry),你不需要初始化这个指针
*/
#define for_each_idr_entry_continue(idp, id, ptr) \
for (ptr = idr_find_next_getid(idp, id - 1, &id); ptr != NULL || !idr_count(idp, id); ptr = idr_find_next_getid(idp, id, &id))
/**
* ida: 基于IDR实现的ID分配器
@ -132,8 +163,11 @@ struct ida
* 对外函数声明
*/
void ida_init(struct ida *ida_p);
int ida_pre_get(struct ida *ida_p, gfp_t gfp_mask);
int ida_get_new(struct ida *ida_p, int *p_id);
bool ida_empty(struct ida *ida_p);
int ida_preload(struct ida *ida_p, gfp_t gfp_mask);
int ida_alloc(struct ida *ida_p, int *p_id);
bool ida_count(struct ida *ida_p, int id);
void ida_remove(struct ida *ida_p, int id);
void ida_destroy(struct ida *ida_p);
void ida_destroy(struct ida *ida_p);
#pragma GCC pop_options