diff --git a/docs/kernel/core_api/data_structures.md b/docs/kernel/core_api/data_structures.md index 4880bf32..1d8aa519 100644 --- a/docs/kernel/core_api/data_structures.md +++ b/docs/kernel/core_api/data_structures.md @@ -2,6 +2,7 @@   内核中实现了常用的几种数据结构,这里是他们的api文档。 +-------------- ## kfifo先进先出缓冲区   kfifo先进先出缓冲区定义于`common/kfifo.h`中。您可以使用它,创建指定大小的fifo缓冲区(最大大小为4GB) @@ -252,3 +253,434 @@ | 满 | 1 | | 不满 | 0 | +------------------ + +## ID Allocation + +   ida的主要作用是分配+管理id. 它能分配一个最小的, 未被分配出去的id. 当您需要管理某个数据结构时, 可能需要使用id来区分不同的目标. 这个时候, ida将会是很好的选择. 因为ida的十分高效, 运行常数相对数组更小, 而且提供了基本管理id需要用到的功能, 值得您试一试. + +  IDA定义于`idr.h`文件中. 您通过`DECLARE_IDA(my_ida)`来创建一个ida对象, 或者`struct ida my_ida; ida_init(my_ida);`来初始化一个ida. + +### ida_init +`void ida_init(struct ida *ida_p)` + +#### 描述 + +  通初始化IDA, 你需要保证调用函数之前, ida的free_list为空, 否则会导致内存泄漏. +#### 参数 + +**ida_p** + +   指向ida的指针 + +#### 返回值 + +  无返回值 + +### ida_preload +`int ida_preload(struct ida *ida_p, gfp_t gfp_mask)` + +#### 描述 + +  为ida预分配空间.您可以不自行调用, 因为当ida需要空间的时候, 内部会自行使用`kmalloc`函数获取空间. 当然, 设计这个函数的目的是为了让您有更多的选择. 当您提前调用这个函数, 可以避免之后在开辟空间上的时间开销. +#### 参数 + +**ida_p** + +   指向ida的指针 + +**gfp_mask** + +   保留参数, 目前尚未使用. + +#### 返回值 + +  如果分配成功,将返回0; 否则返回负数错误码, 有可能是内存空间不够. + + +### ida_alloc +`int ida_alloc(struct ida *ida_p, int *p_id)` + +#### 描述 + +  获取一个空闲ID. 您需要注意, 返回值是成功/错误码. +#### 参数 + +**ida_p** + +   指向ida的指针 + +**p_id** + +   您需要传入一个int变量的指针, 如果成功分配ID, ID将会存储在该指针所指向的地址. + +#### 返回值 + +  如果分配成功,将返回0; 否则返回负数错误码, 有可能是内存空间不够. + + +### ida_count +`bool ida_count(struct ida *ida_p, int id)` + +#### 描述 + +  查询一个ID是否被分配. +#### 参数 + +**ida_p** + +   指向ida的指针 + +**id** + +   您查询该ID是否被分配. + +#### 返回值 + +  如果分配,将返回true; 否则返回false. + + + +### ida_remove +`void ida_remove(struct ida *ida_p, int id)` + +#### 描述 + +  删除一个已经分配的ID. 如果该ID不存在, 该函数不会产生异常错误, 因为在检测到该ID不存在的时候, 函数将会自动退出. +#### 参数 + +**ida_p** + +   指向ida的指针 + +**id** + +   您要删除的id. + +#### 返回值 + +  无返回值. + +### ida_destroy +`void ida_destroy(struct ida *ida_p)` + +#### 描述 + +  释放一个IDA所有的空间, 同时删除ida的所有已经分配的id.(所以您不用担心删除id之后, ida还会占用大量空间.) +#### 参数 + +**ida_p** + +   指向ida的指针 + +#### 返回值 + +  无返回值 + +### ida_empty +`void ida_empty(struct ida *ida_p)` + +#### 描述 + +   查询一个ida是否为空 +#### 参数 + +**ida_p** + +   指向ida的指针 + +#### 返回值 + +  ida为空则返回true,否则返回false。 + + +-------------------- + + +## IDR + +   idr是一个基于radix-tree的ID-pointer的数据结构. 该数据结构提供了建id与数据指针绑定的功能, 它的主要功能有以下4个: +1. 获取一个ID, 并且将该ID与一个指针绑定 +2. 删除一个已分配的ID +3. 根据ID查找对应的指针 +4. 根据ID使用新的ptr替换旧的ptr +   您可以使用`DECLARE_idr(my_idr)`来创建一个idr。或者您也可以使用`struct idr my_idr; idr_init(my_idr);`这两句话创建一个idr。 +   至于什么是radix-tree,您可以把他简单理解为一个向上生长的多叉树,在实现中,我们选取了64叉树。 + +### idr_init +`void idr_init(struct idr *idp)` + +#### 描述 + +  通初始化IDR, 你需要保证调用函数之前, idr的free_list为空, 否则会导致内存泄漏. +#### 参数 + +**idp** + +   指向idr的指针 + +#### 返回值 + +  无返回值 + +### idr_preload +`int idr_preload(struct idr *idp, gfp_t gfp_mask)` + +#### 描述 + +  为idr预分配空间.您可以不自行调用, 因为当idr需要空间的时候, 内部会自行使用`kmalloc`函数获取空间. 当然, 设计这个函数的目的是为了让您有更多的选择. 当您提前调用这个函数, 可以避免之后在开辟空间上的时间开销. +#### 参数 + +**idp** + +   指向idr的指针 + +**gfp_mask** + +   保留参数, 目前尚未使用. + +#### 返回值 + +  如果分配成功,将返回0; 否则返回负数错误码, 有可能是内存空间不够. + + +### idr_alloc +`int idr_alloc(struct idr *idp, void *ptr, int *id)` + +#### 描述 + +   获取一个空闲ID. 您需要注意, 返回值是成功/错误码. +   调用这个函数,需要您保证ptr是非空的,即: `ptr != NULL`, 否则将会影响 `idr_find/idr_find_next/idr_find_next_getid/...`等函数的使用。(具体请看这三个函数的说明,当然,只会影响到您的使用体验,并不会影响到idr内部函数的决策和逻辑) +#### 参数 + +**idp** + +   指向ida的指针 + +**ptr** + +   指向数据的指针 + +**id** + +   您需要传入一个int变量的指针, 如果成功分配ID, ID将会存储在该指针所指向的地址. + +#### 返回值 + +  如果分配成功,将返回0; 否则返回负数错误码, 有可能是内存空间不够. + + +### idr_remove +`void* idr_remove(struct idr *idp, int id)` + +#### 描述 + +  删除一个id, 但是不释放对应的ptr指向的空间, 同时返回这个被删除id所对应的ptr。 +   如果该ID不存在, 该函数不会产生异常错误, 因为在检测到该ID不存在的时候, 函数将会自动退出,并返回NULL。 +#### 参数 + +**idp** + +   指向idr的指针 + +**id** + +   您要删除的id. + +#### 返回值 + +  如果删除成功,就返回被删除id所对应的ptr;否则返回NULL。注意:如果这个id本来就和NULL绑定,那么也会返回NULL + + +### idr_remove_all +`void idr_remove_all(struct idr *idp)` + +#### 描述 + +  删除idr的所有已经分配的id.(所以您不用担心删除id之后, idr还会占用大量空间。) + +   但是你需要注意的是,调用这个函数是不会释放数据指针指向的空间的。 所以您调用该函数之前, 确保IDR内部的数据指针被保存。否则当IDR删除所有ID之后, 将会造成内存泄漏。 + +#### 参数 + +**idp** + +   指向idr的指针 + +#### 返回值 + +  无返回值 + + +### idr_destroy +`void idr_destroy(struct idr *idp)` + +#### 描述 + +  释放一个IDR所有的空间, 同时删除idr的所有已经分配的id.(所以您不用担心删除id之后, ida还会占用大量空间.) - 和`idr_remove_all`的区别是, 释放掉所有的空间(包括free_list的预分配空间)。 +#### 参数 + +**idp** + +   指向idr的指针 + +#### 返回值 + +  无返回值 + + +### idr_find +`void *idr_find(struct idr *idp, int id)` + +#### 描述 + +  查询一个ID所绑定的数据指针 +#### 参数 + +**idp** + +   指向idr的指针 + +**id** + +   您查询该ID的数据指针 + +#### 返回值 + +   如果分配,将返回该ID对应的数据指针; 否则返回NULL.(注意, 返回NULL不一定代表这ID不存在,有可能该ID就是与空指针绑定。) +   当然,我们也提供了`idr_count`函数来判断id是否被分配,具体请查看idr_count介绍。 + +### idr_find_next +`void *idr_find_next(struct idr *idp, int start_id)` + +#### 描述 + +  传进一个start_id,返回满足 "id大于start_id的最小id" 所对应的数据指针。 +#### 参数 + +**idp** + +   指向idr的指针 + +**start_id** + +  您提供的ID限制 + +#### 返回值 + +   如果分配,将返回该ID对应的数据指针; 否则返回NULL.(注意, 返回NULL不一定代表这ID不存在,有可能该ID就是与空指针绑定。) +   当然,我们也提供了`idr_count`函数来判断id是否被分配,具体请查看idr_count介绍。 + + +### idr_find_next_getid +`void *idr_find_next_getid(struct idr *idp, int start_id, int *nextid)` + +#### 描述 + +  传进一个start_id,返回满足 "id大于start_id的最小id" 所对应的数据指针。同时,你获取到这个满足条件的最小id, 即参数中的 *nextid。 +#### 参数 + +**idp** + +   指向idr的指针 + +**start_id** + +   您提供的ID限制 + +#### 返回值 + +   如果分配,将返回该ID对应的数据指针; 否则返回NULL.(注意, 返回NULL不一定代表这ID不存在,有可能该ID就是与空指针绑定。) +   当然,我们也提供了`idr_count`函数来判断id是否被分配,具体请查看idr_count介绍。 + + +### idr_replace +`int idr_replace(struct idr *idp, void *ptr, int id)` + +#### 描述 + +  传进一个ptr,使用该ptr替换掉id所对应的Old_ptr。 +#### 参数 + +**idp** + +   指向idr的指针 + +**ptr** + +  您要替换原来的old_ptr的新指针 + +**id** + +   您要替换的指针所对应的id + +#### 返回值 + +   0代表成功,否则就是错误码 - 代表错误。 + + +### idr_replace_get_old +`int idr_replace_get_old(struct idr *idp, void *ptr, int id, void **oldptr)` + +#### 描述 + +  传进一个ptr,使用该ptr替换掉id所对应的Old_ptr,同时你可以获取到old_ptr。 +#### 参数 + +**idp** + +   指向idr的指针 + +**ptr** + +  您要替换原来的old_ptr的新指针 + +**id** + +   您要替换的指针所对应的id + + +**old_ptr** + +   您需要传进该(void**)指针,old_ptr将会存放在该指针所指向的地址。 + + +#### 返回值 + +   0代表成功,否则就是错误码 - 代表错误。 + +### idr_empty +`void idr_empty(struct idr *idp)` + +#### 描述 + +   查询一个idr是否为空 +#### 参数 + +**idp** + +   指向idr的指针 + +#### 返回值 + +  idr为空则返回true,否则返回false。 + +### idr_count +`bool idr_count(struct idr *idp, int id)` + +#### 描述 + +  查询一个ID是否被分配. +#### 参数 + +**ida_p** + +   指向idr的指针 + +**id** + +   您查询该ID是否被分配. + +#### 返回值 + +  如果分配,将返回true; 否则返回false. \ No newline at end of file diff --git a/kernel/arch/x86_64/math/bitcount.h b/kernel/arch/x86_64/math/bitcount.h index 307d6842..dd2a154d 100644 --- a/kernel/arch/x86_64/math/bitcount.h +++ b/kernel/arch/x86_64/math/bitcount.h @@ -52,4 +52,18 @@ static __always_inline int __clzll(unsigned long long x) : "a"(x) : "memory"); return res; -} \ No newline at end of file +} + +static __always_inline int __ctz(uint32_t x) +{ + asm volatile("tzcnt %%eax, %%eax":"=a"(x):"a"(x):"memory"); + return x; +} + +static __always_inline int __ctzl(unsigned long x) +{ + asm volatile("tzcnt %%rax, %%rax":"=a"(x):"a"(x):"memory"); + return x; +} + +#define __ctzll __ctzl \ No newline at end of file diff --git a/kernel/common/glib.h b/kernel/common/glib.h index 69e67d13..82b344f0 100644 --- a/kernel/common/glib.h +++ b/kernel/common/glib.h @@ -68,7 +68,6 @@ static __always_inline ul ALIGN(const ul addr, const ul _align) } - void *memset(void *dst, unsigned char C, ul size) { diff --git a/kernel/common/idr.h b/kernel/common/idr.h index a631f914..273749fe 100644 --- a/kernel/common/idr.h +++ b/kernel/common/idr.h @@ -1,8 +1,16 @@ - +#pragma GCC push_options +#pragma GCC optimize("O1") #include #include +#if ARCH(I386) || ARCH(X86_64) +#include +#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); \ No newline at end of file +void ida_destroy(struct ida *ida_p); + +#pragma GCC pop_options \ No newline at end of file diff --git a/kernel/ktest/test-idr.c b/kernel/ktest/test-idr.c index 0a9e406d..e4d579f0 100644 --- a/kernel/ktest/test-idr.c +++ b/kernel/ktest/test-idr.c @@ -1,5 +1,6 @@ - +#pragma GCC push_options +#pragma GCC optimize("O1") #include "ktest.h" #include "ktest_utils.h" #include @@ -8,7 +9,7 @@ * @brief 测试idr的构建,预获取空间是否成功 * * 以下函数将被测试: - * 1. idr_pre_get + * 1. idr_preload * 2. DECLARE_IDR * 3. idr_init * 4. idr_destroy @@ -33,7 +34,7 @@ static long ktest_idr_case0(uint64_t arg0, uint64_t arg1) idr_init(&k_idr); assert(k_idr.id_free_cnt == 0); - assert(idr_pre_get(&k_idr, 0) == 0); + assert(idr_preload(&k_idr, 0) == 0); assert(k_idr.id_free_cnt == IDR_FREE_MAX); for (uint64_t i = 1; i < 64; i++) @@ -71,7 +72,7 @@ static long ktest_idr_case1(uint64_t arg0, uint64_t arg1) // 获取128个id for (int i = 0; i < 128; i++) { - assert(idr_get_new(&k_idr, &a[i], &a[i]) == 0); + assert(idr_alloc(&k_idr, &a[i], &a[i]) == 0); assert(a[i] == i); } @@ -87,35 +88,53 @@ static long ktest_idr_case1(uint64_t arg0, uint64_t arg1) // 倒序:删除64个id for (int i = 127; i >= 64; i--) { - idr_remove(&k_idr, a[i]); + int *id = idr_remove(&k_idr, a[i]); + assert(id != NULL); + assert(*id == i); assert(idr_find(&k_idr, a[i]) == NULL); } // 正序:删除64个id for (int i = 0; i <= 63; i++) { - idr_remove(&k_idr, a[i]); + int *id = idr_remove(&k_idr, a[i]); + assert(id != NULL); + assert(*id == i); assert(idr_find(&k_idr, a[i]) == NULL); } + for (int i = 0; i < 128; i++) + { + assert(idr_count(&k_idr, i) == 0); + } + // 重新申请128个id, 值域范围应该仍然是[0,127] for (int i = 0; i < 128; i++) { - assert(idr_get_new(&k_idr, &a[i], &a[i]) == 0); + assert(idr_alloc(&k_idr, &a[i], &a[i]) == 0); assert(a[i] == i); } + for (int i = 0; i < 128; i++) + { + assert(idr_count(&k_idr, i)); + } + // 正序:删除32个id for (int i = 0; i <= 31; i++) { - idr_remove(&k_idr, a[i]); + int *id = idr_remove(&k_idr, a[i]); + assert(id != NULL); + assert(*id == i); assert(idr_find(&k_idr, a[i]) == NULL); } // 倒序:删除32个id for (int i = 127; i >= 96; i--) { - idr_remove(&k_idr, a[i]); + int *id = idr_remove(&k_idr, a[i]); + assert(id != NULL); + assert(*id == i); assert(idr_find(&k_idr, a[i]) == NULL); } @@ -126,7 +145,7 @@ static long ktest_idr_case1(uint64_t arg0, uint64_t arg1) // 获取128个id for (int i = 0; i < 128; i++) { - assert(idr_get_new(&k_idr, &a[i], &a[i]) == 0); + assert(idr_alloc(&k_idr, &a[i], &a[i]) == 0); assert(a[i] == i); } @@ -171,20 +190,30 @@ static long ktest_idr_case2(uint64_t arg0, uint64_t arg1) DECLARE_IDR(k_idr); // 获取 1000‘000 个ID - const int N = 1e7; - const int M = 3e6; + const int N = 1e6; + // const int N = 1048576; + const int M = 2e5; - int tmp; + int tmp=0; for (int i = 0; i < N; i++) { - assert(idr_get_new(&k_idr, &tmp, &tmp) == 0); + barrier(); + assert(idr_alloc(&k_idr, &tmp, &tmp) == 0); + barrier(); assert(tmp == i); + barrier(); int *ptr = idr_find(&k_idr, i); + barrier(); assert(ptr != NULL); assert(*ptr == i); - } + barrier(); + // if (i >= 7255) kdebug("1e6 !!!!!!! : %d", i); + assert(idr_count(&k_idr, i)); + barrier(); + } +// kdebug("111111"); // 正向: M 个ID for (int i = 0; i < M; i++) { @@ -194,6 +223,7 @@ static long ktest_idr_case2(uint64_t arg0, uint64_t arg1) idr_remove(&k_idr, i); assert(idr_find(&k_idr, i) == NULL); } + // kdebug("22222"); // 倒序: N-M 个ID for (int i = (N)-1; i >= M; i--) @@ -203,11 +233,11 @@ static long ktest_idr_case2(uint64_t arg0, uint64_t arg1) idr_remove(&k_idr, i); assert(idr_find(&k_idr, i) == NULL); } - +// kdebug("3333333"); // 重新插入数据 for (int i = 0; i < N; i++) { - assert(idr_get_new(&k_idr, &tmp, &tmp) == 0); + assert(idr_alloc(&k_idr, &tmp, &tmp) == 0); assert(tmp == i); assert(k_idr.top != NULL); @@ -215,19 +245,19 @@ static long ktest_idr_case2(uint64_t arg0, uint64_t arg1) assert(ptr != NULL); assert(*ptr == i); } - +// kdebug("4444444444"); assert(k_idr.top != NULL); for (int i = 0; i < M; i++) { assert(idr_replace(&k_idr, NULL, i) == 0); } - +// kdebug("555555555555555555"); // 销毁 idr_destroy(&k_idr); assert(k_idr.id_free_cnt == 0); assert(k_idr.free_list == NULL); - +// kdebug("666666666666"); return 0; } @@ -247,7 +277,7 @@ static long ktest_idr_case3(uint64_t arg0, uint64_t arg1) // 获取ID for (int i = 0; i < N; i++) { - assert(idr_get_new(&k_idr, &tmp, &tmp) == 0); + assert(idr_alloc(&k_idr, &tmp, &tmp) == 0); assert(tmp == i); int *ptr = idr_find(&k_idr, i); @@ -333,7 +363,7 @@ static long ktest_idr_case4(uint64_t arg0, uint64_t arg1) int M = N / i, T = M / 3, O = 2 * T; for (int j = 0; j < M; j++) { - assert(idr_get_new(&k_idr, &tmp, &tmp) == 0); + assert(idr_alloc(&k_idr, &tmp, &tmp) == 0); assert(tmp == j); } @@ -362,12 +392,14 @@ static long ktest_idr_case4(uint64_t arg0, uint64_t arg1) } assert(k_idr.top == NULL); + assert(idr_empty(&k_idr)); } // 销毁 idr_destroy(&k_idr); assert(k_idr.id_free_cnt == 0); assert(k_idr.free_list == NULL); + assert(idr_empty(&k_idr)); return 0; } @@ -387,7 +419,7 @@ static long ktest_idr_case5(uint64_t arg0, uint64_t arg1) // 获取128个id for (int i = 0; i < N; i++) { - assert(idr_get_new(&k_idr, &a[i], &a[i]) == 0); + assert(idr_alloc(&k_idr, &a[i], &a[i]) == 0); assert(a[i] == i); } @@ -414,12 +446,13 @@ static long ktest_idr_case5(uint64_t arg0, uint64_t arg1) // destroy之后,再获取128个id for (int i = 0; i < N; i++) { - assert(idr_get_new(&k_idr, &a[i], &a[i]) == 0); + assert(idr_alloc(&k_idr, &a[i], &a[i]) == 0); assert(a[i] == i); } // 销毁 idr_destroy(&k_idr); + assert(idr_empty(&k_idr)); assert(k_idr.id_free_cnt == 0); assert(k_idr.free_list == NULL); @@ -442,65 +475,68 @@ static long ktest_idr_case6(uint64_t arg0, uint64_t arg1) DECLARE_IDA(k_ida); ida_init(&k_ida); + io_sfence(); const int N = IDA_FULL * IDR_SIZE + 1; for (int i = 0; i < N; i++) { - int p_id; - assert(ida_get_new(&k_ida, &p_id) == 0); - assert(p_id == i); + int p_id;io_sfence(); + assert(ida_alloc(&k_ida, &p_id) == 0);io_sfence(); + assert(p_id == i);io_sfence(); } for (int i = 0; i < N; i++) { - assert(ida_count(&k_ida, i) == 1); + assert(ida_count(&k_ida, i) == 1);io_sfence(); } for (int i = N - 1; i >= 0; i--) { - ida_remove(&k_ida, i); - assert(ida_count(&k_ida, i) == 0); + ida_remove(&k_ida, i);io_sfence(); + assert(ida_count(&k_ida, i) == 0);io_sfence(); } assert(k_ida.idr.top == NULL); for (int i = 0; i < N; i++) { - int p_id; - assert(ida_get_new(&k_ida, &p_id) == 0); - assert(p_id == i); + int p_id;io_sfence(); + assert(ida_alloc(&k_ida, &p_id) == 0);io_sfence(); + assert(p_id == i);io_sfence(); } - assert(k_ida.idr.top != NULL); - ida_destroy(&k_ida); - assert(k_ida.idr.top == NULL); - assert(k_ida.free_list == NULL); + assert(k_ida.idr.top != NULL);io_sfence(); + ida_destroy(&k_ida);io_sfence(); + assert(k_ida.idr.top == NULL);io_sfence(); + assert(k_ida.free_list == NULL);io_sfence(); + assert(ida_empty(&k_ida));io_sfence(); // 测试destroy之后能否重新获取ID for (int i = 0; i < N; i++) { - int p_id; - assert(ida_get_new(&k_ida, &p_id) == 0); - assert(p_id == i); + int p_id;io_sfence(); + assert(ida_alloc(&k_ida, &p_id) == 0);io_sfence(); + assert(p_id == i);io_sfence(); } for (int i = 0; i < N / 3; i++) { - ida_remove(&k_ida, i); - assert(ida_count(&k_ida, i) == 0); + ida_remove(&k_ida, i);io_sfence(); + assert(ida_count(&k_ida, i) == 0);io_sfence(); } for (int i = 2 * N / 3; i < N; i++) { - ida_remove(&k_ida, i); - assert(ida_count(&k_ida, i) == 0); + ida_remove(&k_ida, i);io_sfence(); + assert(ida_count(&k_ida, i) == 0);io_sfence(); } - assert(k_ida.idr.top != NULL); - ida_destroy(&k_ida); - assert(k_ida.idr.top == NULL); - assert(k_ida.free_list == NULL); + assert(k_ida.idr.top != NULL);io_sfence(); + ida_destroy(&k_ida);io_sfence(); + assert(k_ida.idr.top == NULL);io_sfence(); + assert(k_ida.free_list == NULL);io_sfence(); + assert(ida_empty(&k_ida));io_sfence(); return 0; } @@ -526,4 +562,6 @@ int ktest_test_idr(void* arg) } kTEST("idr Test done."); return 0; -} \ No newline at end of file +} + +#pragma GCC pop_options \ No newline at end of file diff --git a/kernel/lib/idr.c b/kernel/lib/idr.c index 79a6adb4..71705d24 100644 --- a/kernel/lib/idr.c +++ b/kernel/lib/idr.c @@ -1,5 +1,7 @@ #include #include +#pragma GCC push_options +#pragma GCC optimize("O0") /** * @brief 更换两个idr_layer指针 @@ -32,14 +34,17 @@ void idr_init(struct idr *idp) */ static void __move_to_free_list(struct idr *idp, struct idr_layer *p) { - spin_lock(&idp->lock); + unsigned long flags; + spin_lock_irqsave(&idp->lock, flags); // 插入free_list p->ary[0] = idp->free_list; + io_sfence(); idp->free_list = p; + io_sfence(); ++(idp->id_free_cnt); - spin_unlock(&idp->lock); + spin_unlock_irqrestore(&idp->lock, flags); } /** @@ -52,22 +57,32 @@ static void *__get_from_free_list(struct idr *idp) { if (idp->id_free_cnt == 0) { - if (idr_pre_get(idp, 0) != 0) + if (idr_preload(idp, 0) != 0) { kBUG("idr-module find a BUG: get free node fail.(Possible ENOMEM error)"); return NULL; } } - spin_lock(&idp->lock); + unsigned long flags; + spin_lock_irqsave(&idp->lock, flags); // free_list还有节点 struct idr_layer *item = idp->free_list; + + if (item == NULL) + { + BUG_ON(1); + } + + io_sfence(); idp->free_list = idp->free_list->ary[0]; + io_sfence(); item->ary[0] = NULL; // 记得清空原来的数据 + io_sfence(); --(idp->id_free_cnt); - spin_unlock(&idp->lock); + spin_unlock_irqrestore(&idp->lock, flags); return item; } @@ -79,15 +94,16 @@ static void *__get_from_free_list(struct idr *idp) * @param gfp_mask * @return int (如果分配成功,将返回0; 否则返回负数 -ENOMEM, 有可能是内存空间不够) */ -int idr_pre_get(struct idr *idp, gfp_t gfp_mask) +int idr_preload(struct idr *idp, gfp_t gfp_mask) { int timer = 0; while (idp->id_free_cnt < IDR_FREE_MAX) { struct idr_layer *new_one; new_one = kzalloc(sizeof(struct idr_layer), gfp_mask); // 默认清空? - if (NULL == new_one) + if (unlikely(new_one == NULL)) return -ENOMEM; + __move_to_free_list(idp, new_one); timer++; } @@ -149,9 +165,9 @@ static int __idr_get_empty_slot(struct idr *idp, struct idr_layer **stk) if (__idr_grow(idp) != 0) return -ENOMEM; - int id = 0; + int64_t id = 0; int layer = idp->top->layer; - + BUG_ON(layer + 1 >= 7); stk[layer + 1] = NULL; // 标志为数组末尾 struct idr_layer *cur_layer = idp->top; @@ -198,6 +214,7 @@ static int __idr_get_empty_slot(struct idr *idp, struct idr_layer **stk) */ static __always_inline void __idr_mark_full(struct idr *idp, int id, struct idr_layer **stk, int mark) { + int64_t __id = (int64_t)id; if (unlikely(NULL == stk[0] || NULL == idp->top)) { kBUG("idr-module find a BUG: idp->top can't be NULL."); @@ -205,7 +222,7 @@ static __always_inline void __idr_mark_full(struct idr *idp, int id, struct idr_ } // 处理叶子节点的full/bitmap标记 - int layer_id = id & IDR_MASK; + int layer_id = __id & IDR_MASK; if (mark == 2) stk[0]->full |= (1ull << layer_id); if (mark >= 1) @@ -213,8 +230,8 @@ static __always_inline void __idr_mark_full(struct idr *idp, int id, struct idr_ for (int i = 1; stk[i]; ++i) { - id >>= IDR_BITS; - layer_id = id & IDR_MASK; + __id >>= IDR_BITS; + layer_id = __id & IDR_MASK; stk[i]->bitmap |= (1ull << layer_id); if (stk[i - 1]->full == IDR_FULL) @@ -232,7 +249,8 @@ static __always_inline void __idr_mark_full(struct idr *idp, int id, struct idr_ */ static __always_inline int __idr_get_path(struct idr *idp, int id, struct idr_layer **stk) { - if (unlikely(idp->top == NULL || id < 0)) + int64_t __id = (int64_t)id; + if (unlikely(idp->top == NULL || __id < 0)) { kBUG("idr-module find a BUG: idp->top can't be NULL and id must be non-negative."); return 0; @@ -242,11 +260,17 @@ static __always_inline int __idr_get_path(struct idr *idp, int id, struct idr_la int layer = cur_layer->layer; stk[layer + 1] = NULL; // 标志数组结尾 + if (unlikely((__id >> ((layer + 1ull) * IDR_BITS)) > 0)) + { + kBUG("idr-module find a BUG: id is invalid."); + return 0; + } + // 提取路径 while (layer >= 0) { stk[layer] = cur_layer; - int layer_id = (id >> (layer * IDR_BITS)) & IDR_MASK; + int layer_id = (__id >> (layer * IDR_BITS)) & IDR_MASK; if (unlikely(((cur_layer->bitmap >> layer_id) & 1) == 0)) { @@ -271,6 +295,7 @@ static __always_inline int __idr_get_path(struct idr *idp, int id, struct idr_la */ static __always_inline void __idr_erase_full(struct idr *idp, int id, struct idr_layer **stk, int mark) { + int64_t __id = (int64_t)id; if (unlikely(NULL == stk[0] || NULL == idp->top)) { kBUG("idr-module find a BUG: idp->top can't be NULL."); @@ -278,7 +303,7 @@ static __always_inline void __idr_erase_full(struct idr *idp, int id, struct idr } // 处理叶子节点的full/bitmap标记 - int layer_id = id & IDR_MASK; + int layer_id = __id & IDR_MASK; if (mark == 0) // 叶子的某个插槽为空 { stk[0]->ary[layer_id] = NULL; @@ -290,8 +315,8 @@ static __always_inline void __idr_erase_full(struct idr *idp, int id, struct idr // 删除节点 for (int layer = 1; stk[layer]; ++layer) { - id >>= IDR_BITS; - layer_id = id & IDR_MASK; + __id >>= IDR_BITS; + layer_id = __id & IDR_MASK; if (NULL == stk[layer - 1]->bitmap) // 儿子是空节点 { @@ -333,8 +358,12 @@ static __always_inline void __idr_erase_full(struct idr *idp, int id, struct idr */ static int __idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id) { - struct idr_layer *stk[MAX_LEVEL + 1]; // 你可以选择memset(0) - int id = __idr_get_empty_slot(idp, stk); + struct idr_layer *stk[MAX_LEVEL + 1] = {0}; + + // kdebug("stk=%#018lx, sizeof_stk=%d", stk, sizeof(stk)); + // memset(stk, 0, sizeof(stk)); + // 你可以选择 memset(stk, 0, sizeof(stk)); + int64_t id = __idr_get_empty_slot(idp, stk); if (id >= 0) { @@ -353,7 +382,7 @@ static int __idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id) * @param int* id - 传入int指针,获取到的NEW_ID存在id里 * @return int (0表示获取id成功, 负数代表错误 - 可能是内存空间不够) */ -int idr_get_new(struct idr *idp, void *ptr, int *id) +int idr_alloc(struct idr *idp, void *ptr, int *id) { int rv = __idr_get_new_above_int(idp, ptr, 0); if (rv < 0) @@ -363,21 +392,28 @@ int idr_get_new(struct idr *idp, void *ptr, int *id) } /** - * @brief 删除一个id,但是不释放对应的ptr指向的空间 + * @brief 删除一个id, 但是不释放对应的ptr指向的空间, 同时返回这个被删除id所对应的ptr * * @param idp * @param id + * @return void* + * (如果删除成功,就返回被删除id所对应的ptr;否则返回NULL。注意:如果这个id本来就和NULL绑定,那么也会返回NULL) */ -void idr_remove(struct idr *idp, int id) +void *idr_remove(struct idr *idp, int id) { - if (unlikely(idp->top == NULL || id < 0)) - return; + int64_t __id = (int64_t)id; + if (unlikely(idp->top == NULL || __id < 0)) + return NULL; - struct idr_layer *stk[MAX_LEVEL + 1]; - if (0 == __idr_get_path(idp, id, stk)) - return; // 找不到路径 + struct idr_layer *stk[MAX_LEVEL + 1] = {0}; - __idr_erase_full(idp, id, stk, 0); + if (0 == __idr_get_path(idp, __id, stk)) + return NULL; // 找不到路径 + + void *ret = stk[0]->ary[__id & IDR_MASK]; + __idr_erase_full(idp, __id, stk, 0); + + return ret; } /** @@ -395,9 +431,11 @@ static void __idr_remove_all_with_free(struct idr *idp, bool free) } int sz = sizeof(struct idr_layer); - struct idr_layer *stk[MAX_LEVEL + 1]; + struct idr_layer *stk[MAX_LEVEL + 1] = {0}; + struct idr_layer *cur_layer = idp->top; int layer = cur_layer->layer; + BUG_ON(layer + 1 >= 7); stk[layer + 1] = NULL; // 标记数组结尾 while (cur_layer != NULL) @@ -405,7 +443,7 @@ static void __idr_remove_all_with_free(struct idr *idp, bool free) if (layer > 0 && cur_layer->bitmap) // 非叶子节点 { stk[layer] = cur_layer; // 入栈 - int id = __lowbit_id(cur_layer->bitmap); + int64_t id = __lowbit_id(cur_layer->bitmap); cur_layer->bitmap ^= (1ull << id); cur_layer = cur_layer->ary[id]; @@ -482,19 +520,21 @@ void idr_destroy(struct idr *idp) */ void *idr_find(struct idr *idp, int id) { - if (unlikely(idp->top == NULL || id < 0)) + int64_t __id = (int64_t)id; + if (unlikely(idp->top == NULL || __id < 0)) + { + kwarn("idr-find: idp->top == NULL || id < 0."); return NULL; + } struct idr_layer *cur_layer = idp->top; int layer = cur_layer->layer; // 特判NULL - // 如果查询的ID的bit数量比layer*IDR_BITS还大, 直接返回NULL - if ((id >> ((layer + 1) * IDR_BITS)) > 0) + if ((__id >> ((layer + 1) * IDR_BITS)) > 0) return NULL; - while (layer >= 0 && cur_layer) { - int layer_id = (id >> (IDR_BITS * layer)) & IDR_MASK; + int layer_id = (__id >> (IDR_BITS * layer)) & IDR_MASK; cur_layer = cur_layer->ary[layer_id]; --layer; } @@ -508,10 +548,12 @@ void *idr_find(struct idr *idp, int id) * @param idp * @param start_id * @param nextid - * @return void* + * @return void* (如果分配,将返回该ID对应的数据指针; 否则返回NULL。注意, + * 返回NULL不一定代表这ID不存在,有可能该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) { + BUG_ON(nextid == NULL); if (unlikely(idp->top == NULL)) { *nextid = -1; @@ -522,16 +564,20 @@ void *idr_find_next_getid(struct idr *idp, int start_id, int *nextid) start_id = max(0, start_id); // 特判负数 *nextid = 0; - struct idr_layer *stk[MAX_LEVEL + 1]; - bool state[MAX_LEVEL + 1]; // 标记是否大于等于] - int pos_i[MAX_LEVEL + 1]; + struct idr_layer *stk[MAX_LEVEL + 1] = {0}; - memset(pos_i, 0, sizeof(pos_i)); // 必须清空 + // memset(stk, 0, sizeof(struct idr_layer *) * (MAX_LEVEL + 1)); + bool state[MAX_LEVEL + 1] = {0}; // 标记是否大于等于] + int pos_i[MAX_LEVEL + 1] = {0}; + + // memset(state, 0, sizeof(state)); + // memset(pos_i, 0, sizeof(pos_i)); // 必须清空 struct idr_layer *cur_layer = idp->top; bool cur_state = false; bool init_flag = true; int layer = cur_layer->layer; + BUG_ON(layer + 1 >= 7); stk[layer + 1] = NULL; // 标记数组结尾 // 如果查询的ID的bit数量比layer*IDR_BITS还大, 直接返回NULL @@ -543,6 +589,7 @@ void *idr_find_next_getid(struct idr *idp, int start_id, int *nextid) while (cur_layer) // layer < top->layer + 1 { + BUG_ON(layer < 0); if (init_flag) // 第一次入栈 { stk[layer] = cur_layer; @@ -555,13 +602,14 @@ void *idr_find_next_getid(struct idr *idp, int start_id, int *nextid) state[layer] = cur_state = true; } + BUG_ON(pos_i[layer] >= 64); unsigned long t_bitmap = (cur_layer->bitmap >> pos_i[layer]); if (t_bitmap) // 进一步递归到儿子下面去 { int layer_id = __lowbit_id(t_bitmap) + pos_i[layer]; // 特别情况 - if (NULL == cur_state && layer_id > pos_i[layer] > 0) + if ((cur_state == false) && layer_id > pos_i[layer] > 0) cur_state = true; pos_i[layer] = layer_id; @@ -596,7 +644,8 @@ void *idr_find_next_getid(struct idr *idp, int start_id, int *nextid) * * @param idp * @param start_id - * @return void* + * @return void* (如果分配,将返回该ID对应的数据指针; 否则返回NULL。注意, + * 返回NULL不一定代表这ID不存在,有可能该ID就是与空指针绑定。) */ void *idr_find_next(struct idr *idp, int start_id) { @@ -617,21 +666,26 @@ void *idr_find_next(struct idr *idp, int start_id) */ int idr_replace_get_old(struct idr *idp, void *ptr, int id, void **old_ptr) { + int64_t __id = (int64_t)id; + if (unlikely(old_ptr == NULL)) + { + BUG_ON(1); + return -EINVAL; + } *old_ptr = NULL; - if (unlikely(idp->top == NULL || id < 0)) + if (unlikely(idp->top == NULL || __id < 0)) return -EDOM; // 参数错误 struct idr_layer *cur_layer = idp->top; - int layer = cur_layer->layer; - + int64_t layer = cur_layer->layer; // 如果查询的ID的bit数量比layer*IDR_BITS还大, 直接返回NULL - if ((id >> ((layer + 1) * IDR_BITS)) > 0) + if ((__id >> ((layer + 1) * IDR_BITS)) > 0) return -EDOM; while (layer > 0) { - int layer_id = (id >> (layer * IDR_BITS)) & IDR_MASK; + int layer_id = (__id >> (layer * IDR_BITS)) & IDR_MASK; if (unlikely(NULL == cur_layer->ary[layer_id])) return -ENOMEM; @@ -640,9 +694,9 @@ int idr_replace_get_old(struct idr *idp, void *ptr, int id, void **old_ptr) layer--; } - id &= IDR_MASK; - *old_ptr = cur_layer->ary[id]; - cur_layer->ary[id] = ptr; + __id &= IDR_MASK; + *old_ptr = cur_layer->ary[__id]; + cur_layer->ary[__id] = ptr; return 0; } @@ -657,15 +711,105 @@ int idr_replace_get_old(struct idr *idp, void *ptr, int id, void **old_ptr) */ int idr_replace(struct idr *idp, void *ptr, int id) { - if (id < 0) + int64_t __id = (int64_t)id; + if (__id < 0) return -EDOM; void *old_ptr; - int flags = idr_replace_get_old(idp, ptr, id, &old_ptr); + int flags = idr_replace_get_old(idp, ptr, __id, &old_ptr); return flags; } +/** + * @brief 判断一个idr是否为空 + * + * @param idp + * @return true + * @return false + */ +bool idr_empty(struct idr *idp) +{ + if (idp == NULL || idp->top == NULL || !idp->top->bitmap) + return true; + + return false; +} +#pragma GCC push_options +#pragma GCC optimize("O0") + +static bool __idr_cnt_pd(struct idr_layer *cur_layer, int layer_id) +{ + // if(layer_id) + unsigned long flags = ((cur_layer->bitmap) >> layer_id); + if ((flags % 2) == 0) + { + barrier(); + return false; // 没有这一个儿子 + } + return true; +} + +static bool __idr_cnt(int layer, int id, struct idr_layer *cur_layer) +{ + int64_t __id = (int64_t)id; + while (layer >= 0) // 提取路径 + { + barrier(); + + int layer_id = (__id >> (layer * IDR_BITS)) & IDR_MASK; + + barrier(); + + if (__idr_cnt_pd(cur_layer, layer_id) == false) + return false; + + barrier(); + + barrier(); + cur_layer = cur_layer->ary[layer_id]; + + barrier(); + --layer; + } + return true; +} +#pragma GCC pop_options + +/** + * @brief 这个函数是可以用于判断一个ID是否已经被分配的。 + * + * @param idp + * @param id + * @return true + * @return false + */ +bool idr_count(struct idr *idp, int id) +{ + int64_t __id = (int64_t)id; + barrier(); + if (unlikely(idp == NULL || idp->top == NULL || __id < 0)) + return false; + + barrier(); + struct idr_layer *cur_layer = idp->top; + barrier(); + int layer = cur_layer->layer; + + // 如果查询的ID的bit数量比 layer*IDR_BITS 还大, 直接返回false + if (unlikely((__id >> ((layer + 1ull) * IDR_BITS)) > 0)) + { + BUG_ON(1); + return false; + } + barrier(); + + return __idr_cnt(layer, id, cur_layer); +} + +/********* ****************************************** ida - idr 函数实现分割线 + * **********************************************************/ + /** * @brief 初始化IDA, 你需要保证调用函数之前, ida的free_list为空, 否则会导致内存泄漏 * @param ida_p @@ -692,9 +836,9 @@ static void __ida_bitmap_free(struct ida_bitmap *bitmap) * @param gfp_mask * @return int (如果分配成功,将返回0; 否则返回负数错误码, 有可能是内存空间不够) */ -int ida_pre_get(struct ida *ida_p, gfp_t gfp_mask) +int ida_preload(struct ida *ida_p, gfp_t gfp_mask) { - if (idr_pre_get(&ida_p->idr, gfp_mask) != 0) + if (idr_preload(&ida_p->idr, gfp_mask) != 0) return -ENOMEM; spin_lock(&ida_p->idr.lock); @@ -724,8 +868,11 @@ int ida_pre_get(struct ida *ida_p, gfp_t gfp_mask) static void *__get_ida_bitmap(struct ida *ida_p, gfp_t gfp_mask) { if (NULL == ida_p->free_list) - if (ida_pre_get(ida_p, gfp_mask) < 0) + if (ida_preload(ida_p, gfp_mask) < 0) + { + kBUG("error : no memory."); return NULL; + } struct ida_bitmap *tmp = ida_p->free_list; ida_p->free_list = NULL; @@ -749,7 +896,8 @@ static int __get_id_from_bitmap(struct ida_bitmap *bmp) if (unlikely((unsigned long long)ary_id * IDA_BMP_SIZE + bmp_id > INT32_MAX)) { - kBUG("ida设置id范围为[0, INT32_MAX], 但ida获取的id数值超过INT32_MAX."); + BUG_ON(1); + // kBUG("ida设置id范围为[0, INT32_MAX], 但ida获取的id数值超过INT32_MAX."); return -EDOM; } @@ -767,13 +915,17 @@ static int __get_id_from_bitmap(struct ida_bitmap *bmp) * @param p_id * @return int (0表示获取ID成功, 否则是负数 - 错误码) */ -int ida_get_new(struct ida *ida_p, int *p_id) +int ida_alloc(struct ida *ida_p, int *p_id) { + BUG_ON(p_id == NULL); *p_id = -1; - struct idr_layer *stk[MAX_LEVEL + 1]; // 你可以选择memset(0) - memset(stk, 0, sizeof(stk)); - int idr_id = __idr_get_empty_slot(&ida_p->idr, stk); + struct idr_layer *stk[MAX_LEVEL + 1] = {0}; // 你可以选择memset(0) + + // memset(stk, 0, sizeof(struct idr_layer *) * (MAX_LEVEL + 1)); + + io_sfence(); + int64_t idr_id = __idr_get_empty_slot(&ida_p->idr, stk); // 如果stk[0]=NULL,可能是idr内部出错/内存空间不够 if (unlikely(NULL == stk[0])) @@ -812,12 +964,13 @@ int ida_get_new(struct ida *ida_p, int *p_id) */ bool ida_count(struct ida *ida_p, int id) { + int64_t __id = (int64_t)id; if (unlikely(NULL == ida_p || NULL == ida_p->idr.top || id < 0)) return false; - int idr_id = id / IDA_BITMAP_BITS; - int ary_id = (id % IDA_BITMAP_BITS) / IDA_BMP_SIZE; - int bmp_id = (id % IDA_BITMAP_BITS) % IDA_BMP_SIZE; + int idr_id = __id / IDA_BITMAP_BITS; + int ary_id = (__id % IDA_BITMAP_BITS) / IDA_BMP_SIZE; + int bmp_id = (__id % IDA_BITMAP_BITS) % IDA_BMP_SIZE; struct ida_bitmap *bmp = idr_find(&ida_p->idr, idr_id); if (NULL == bmp) @@ -834,19 +987,21 @@ bool ida_count(struct ida *ida_p, int id) */ void ida_remove(struct ida *ida_p, int id) { + int64_t __id = (int64_t)id; if (unlikely(NULL == ida_p || NULL == ida_p->idr.top || id < 0)) return; - int idr_id = id / IDA_BITMAP_BITS; - int ary_id = (id % IDA_BITMAP_BITS) / IDA_BMP_SIZE; - int bmp_id = (id % IDA_BITMAP_BITS) % IDA_BMP_SIZE; + int64_t idr_id = __id / IDA_BITMAP_BITS; + int64_t ary_id = (__id % IDA_BITMAP_BITS) / IDA_BMP_SIZE; + int64_t bmp_id = (__id % IDA_BITMAP_BITS) % IDA_BMP_SIZE; + + struct idr_layer *stk[MAX_LEVEL + 1] = {0}; + // memset(stk, 0, sizeof(struct idr_layer *) * (MAX_LEVEL + 1)); - struct idr_layer *stk[MAX_LEVEL + 1]; - memset(stk, 0, sizeof(stk)); if (0 == __idr_get_path(&ida_p->idr, idr_id, stk)) return; - struct ida_bitmap *b_p = (struct ida_bitmap *)stk[0]->ary[idr_id & IDR_MASK]; + struct ida_bitmap *b_p = (struct ida_bitmap *)(stk[0]->ary[idr_id & IDR_MASK]); // 不存在这个ID 或者 b_p == NULL if (unlikely(NULL == b_p || 0 == ((b_p->bitmap[ary_id] >> bmp_id) & 1))) @@ -871,10 +1026,30 @@ void ida_remove(struct ida *ida_p, int id) void ida_destroy(struct ida *ida_p) { if (unlikely(ida_p == NULL)) + { + BUG_ON(1); return; + } __idr_destroy_with_free(&ida_p->idr); ida_p->idr.top = NULL; __ida_bitmap_free(ida_p->free_list); ida_p->free_list = NULL; -} \ No newline at end of file +} + +/** + * @brief 判断一个ida是否为空 + * + * @param ida_p + * @return true + * @return false + */ +bool ida_empty(struct ida *ida_p) +{ + if (ida_p == NULL || ida_p->idr.top == NULL || !ida_p->idr.top->bitmap) + return true; + + return false; +} + +#pragma GCC pop_options \ No newline at end of file diff --git a/kernel/lib/lz4.c b/kernel/lib/lz4.c index b2f92832..893b1e1b 100644 --- a/kernel/lib/lz4.c +++ b/kernel/lib/lz4.c @@ -40,6 +40,14 @@ * Select how default compression functions will allocate memory for their hash table, * in memory stack (0:default, fastest), or in memory heap (1:requires malloc()). */ +#include + +#if ARCH(I386) || ARCH(X86_64) +#include +#else +#error Arch not supported. +#endif + #ifndef LZ4_HEAPMODE #define LZ4_HEAPMODE 0 #endif @@ -589,7 +597,7 @@ static unsigned LZ4_NbCommonBytes(reg_t val) #if (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \ ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \ !defined(__TINYC__) && !defined(LZ4_FORCE_SW_BITCOUNT) - return (unsigned)__builtin_clzll((U64)val) >> 3; + return (unsigned)__clzll((U64)val) >> 3; #else #if 1 /* this method is probably faster, @@ -763,7 +771,7 @@ static unsigned LZ4_NbCommonBytes(reg_t val) #if (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \ ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \ !defined(LZ4_FORCE_SW_BITCOUNT) - return (unsigned)__builtin_clz((U32)val) >> 3; + return (unsigned)__clz((U32)val) >> 3; #else val >>= 8; val = ((((val + 0x00FFFF00) | 0x00FFFFFF) + val) | diff --git a/kernel/process/process.c b/kernel/process/process.c index f3703729..640b9d00 100644 --- a/kernel/process/process.c +++ b/kernel/process/process.c @@ -42,18 +42,19 @@ extern void kernel_thread_func(void); ul _stack_start; // initial proc的栈基地址(虚拟地址) extern struct mm_struct initial_mm; -struct thread_struct initial_thread = - { - .rbp = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), - .rsp = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), - .fs = KERNEL_DS, - .gs = KERNEL_DS, - .cr2 = 0, - .trap_num = 0, - .err_code = 0}; +struct thread_struct initial_thread = { + .rbp = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), + .rsp = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), + .fs = KERNEL_DS, + .gs = KERNEL_DS, + .cr2 = 0, + .trap_num = 0, + .err_code = 0, +}; // 初始化 初始进程的union ,并将其链接到.data.init_proc段内 -union proc_union initial_proc_union __attribute__((__section__(".data.init_proc_union"))) = {INITIAL_PROC(initial_proc_union.pcb)}; +union proc_union initial_proc_union + __attribute__((__section__(".data.init_proc_union"))) = {INITIAL_PROC(initial_proc_union.pcb)}; struct process_control_block *initial_proc[MAX_CPU_NUM] = {&initial_proc_union.pcb, 0}; @@ -110,7 +111,8 @@ uint64_t process_exit_mm(struct process_control_block *pcb); * @param pcb 新的进程的pcb * @return uint64_t */ -uint64_t process_copy_thread(uint64_t clone_flags, struct process_control_block *pcb, uint64_t stack_start, uint64_t stack_size, struct pt_regs *current_regs); +uint64_t process_copy_thread(uint64_t clone_flags, struct process_control_block *pcb, uint64_t stack_start, + uint64_t stack_size, struct pt_regs *current_regs); void process_exit_thread(struct process_control_block *pcb); @@ -128,13 +130,13 @@ void __switch_to(struct process_control_block *prev, struct process_control_bloc { initial_tss[proc_current_cpu_id].rsp0 = next->thread->rbp; // kdebug("next_rsp = %#018lx ", next->thread->rsp); - // set_tss64((uint *)phys_2_virt(TSS64_Table), initial_tss[0].rsp0, initial_tss[0].rsp1, initial_tss[0].rsp2, initial_tss[0].ist1, - // initial_tss[0].ist2, initial_tss[0].ist3, initial_tss[0].ist4, initial_tss[0].ist5, initial_tss[0].ist6, initial_tss[0].ist7); + // set_tss64((uint *)phys_2_virt(TSS64_Table), initial_tss[0].rsp0, initial_tss[0].rsp1, initial_tss[0].rsp2, + // initial_tss[0].ist1, + // initial_tss[0].ist2, initial_tss[0].ist3, initial_tss[0].ist4, initial_tss[0].ist5, + // initial_tss[0].ist6, initial_tss[0].ist7); - __asm__ __volatile__("movq %%fs, %0 \n\t" - : "=a"(prev->thread->fs)); - __asm__ __volatile__("movq %%gs, %0 \n\t" - : "=a"(prev->thread->gs)); + __asm__ __volatile__("movq %%fs, %0 \n\t" : "=a"(prev->thread->fs)); + __asm__ __volatile__("movq %%gs, %0 \n\t" : "=a"(prev->thread->gs)); __asm__ __volatile__("movq %0, %%fs \n\t" ::"a"(next->thread->fs)); __asm__ __volatile__("movq %0, %%gs \n\t" ::"a"(next->thread->gs)); @@ -233,8 +235,8 @@ static int process_load_elf_file(struct pt_regs *regs, char *path) regs->rip = ehdr.e_entry; current_pcb->mm->code_addr_start = ehdr.e_entry; - // kdebug("ehdr.e_phoff=%#018lx\t ehdr.e_phentsize=%d, ehdr.e_phnum=%d", ehdr.e_phoff, ehdr.e_phentsize, ehdr.e_phnum); - // 将指针移动到program header处 + // kdebug("ehdr.e_phoff=%#018lx\t ehdr.e_phentsize=%d, ehdr.e_phnum=%d", ehdr.e_phoff, ehdr.e_phentsize, + // ehdr.e_phnum); 将指针移动到program header处 pos = ehdr.e_phoff; // 读取所有的phdr pos = filp->file_ops->lseek(filp, pos, SEEK_SET); @@ -250,7 +252,8 @@ static int process_load_elf_file(struct pt_regs *regs, char *path) // 将程序加载到内存中 for (int i = 0; i < ehdr.e_phnum; ++i, ++phdr) { - // kdebug("phdr[%d] phdr->p_offset=%#018lx phdr->p_vaddr=%#018lx phdr->p_memsz=%ld phdr->p_filesz=%ld phdr->p_type=%d", i, phdr->p_offset, phdr->p_vaddr, phdr->p_memsz, phdr->p_filesz, phdr->p_type); + // kdebug("phdr[%d] phdr->p_offset=%#018lx phdr->p_vaddr=%#018lx phdr->p_memsz=%ld phdr->p_filesz=%ld + // phdr->p_type=%d", i, phdr->p_offset, phdr->p_vaddr, phdr->p_memsz, phdr->p_filesz, phdr->p_type); // 不是可加载的段 if (phdr->p_type != PT_LOAD) @@ -279,7 +282,8 @@ static int process_load_elf_file(struct pt_regs *regs, char *path) { uint64_t pa = alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys; struct vm_area_struct *vma = NULL; - int ret = mm_create_vma(current_pcb->mm, virt_base, PAGE_2M_SIZE, VM_USER | VM_ACCESS_FLAGS, NULL, &vma); + int ret = + mm_create_vma(current_pcb->mm, virt_base, PAGE_2M_SIZE, VM_USER | VM_ACCESS_FLAGS, NULL, &vma); // 防止内存泄露 if (ret == -EEXIST) @@ -301,7 +305,8 @@ static int process_load_elf_file(struct pt_regs *regs, char *path) uint64_t paddr = virt_2_phys((uint64_t)kmalloc(PAGE_4K_SIZE, 0)); struct vm_area_struct *vma = NULL; - int val = mm_create_vma(current_pcb->mm, virt_base + off, PAGE_4K_SIZE, VM_USER | VM_ACCESS_FLAGS, NULL, &vma); + int val = mm_create_vma(current_pcb->mm, virt_base + off, PAGE_4K_SIZE, VM_USER | VM_ACCESS_FLAGS, + NULL, &vma); // kdebug("virt_base=%#018lx", virt_base + off); if (val == -EEXIST) kfree(phys_2_virt(paddr)); @@ -337,7 +342,8 @@ static int process_load_elf_file(struct pt_regs *regs, char *path) { struct vm_area_struct *vma = NULL; uint64_t pa = alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys; - int val = mm_create_vma(current_pcb->mm, current_pcb->mm->stack_start - PAGE_2M_SIZE, PAGE_2M_SIZE, VM_USER | VM_ACCESS_FLAGS, NULL, &vma); + int val = mm_create_vma(current_pcb->mm, current_pcb->mm->stack_start - PAGE_2M_SIZE, PAGE_2M_SIZE, + VM_USER | VM_ACCESS_FLAGS, NULL, &vma); if (val == -EEXIST) free_pages(Phy_to_2M_Page(pa), 1); else @@ -495,9 +501,7 @@ ul initial_kernel_thread(ul arg) // 对一些组件进行单元测试 uint64_t tpid[] = { - ktest_start(ktest_test_bitree, 0), - ktest_start(ktest_test_kfifo, 0), - ktest_start(ktest_test_mutex, 0), + ktest_start(ktest_test_bitree, 0), ktest_start(ktest_test_kfifo, 0), ktest_start(ktest_test_mutex, 0), ktest_start(ktest_test_idr, 0), // usb_pid, }; @@ -525,14 +529,15 @@ ul initial_kernel_thread(ul arg) regs = (struct pt_regs *)current_pcb->thread->rsp; // kdebug("current_pcb->thread->rsp=%#018lx", current_pcb->thread->rsp); current_pcb->flags = 0; - // 将返回用户层的代码压入堆栈,向rdx传入regs的地址,然后jmp到do_execve这个系统调用api的处理函数 这里的设计思路和switch_proc类似 - // 加载用户态程序:shell.elf + // 将返回用户层的代码压入堆栈,向rdx传入regs的地址,然后jmp到do_execve这个系统调用api的处理函数 + // 这里的设计思路和switch_proc类似 加载用户态程序:shell.elf char init_path[] = "/shell.elf"; uint64_t addr = (uint64_t)&init_path; __asm__ __volatile__("movq %1, %%rsp \n\t" "pushq %2 \n\t" "jmp do_execve \n\t" ::"D"(current_pcb->thread->rsp), - "m"(current_pcb->thread->rsp), "m"(current_pcb->thread->rip), "S"("/shell.elf"), "c"(NULL), "d"(NULL) + "m"(current_pcb->thread->rsp), "m"(current_pcb->thread->rip), "S"("/shell.elf"), "c"(NULL), + "d"(NULL) : "memory"); return 1; @@ -662,7 +667,8 @@ void process_init() * @param stack_size 堆栈大小 * @return unsigned long */ -unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned long stack_start, unsigned long stack_size) +unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned long stack_start, + unsigned long stack_size) { int retval = 0; struct process_control_block *tsk = NULL; @@ -922,7 +928,8 @@ uint64_t process_copy_mm(uint64_t clone_flags, struct process_control_block *pcb memset(phys_2_virt(new_mms->pgd), 0, PAGE_4K_SIZE / 2); // 拷贝内核空间的页表指针 - memcpy(phys_2_virt(new_mms->pgd) + 256, phys_2_virt(initial_proc[proc_current_cpu_id]->mm->pgd) + 256, PAGE_4K_SIZE / 2); + memcpy(phys_2_virt(new_mms->pgd) + 256, phys_2_virt(initial_proc[proc_current_cpu_id]->mm->pgd) + 256, + PAGE_4K_SIZE / 2); uint64_t *current_pgd = (uint64_t *)phys_2_virt(current_pcb->mm->pgd); @@ -948,14 +955,16 @@ uint64_t process_copy_mm(uint64_t clone_flags, struct process_control_block *pcb uint64_t pa = alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys; struct vm_area_struct *new_vma = NULL; - int ret = mm_create_vma(new_mms, vma->vm_start + i * PAGE_2M_SIZE, PAGE_2M_SIZE, vma->vm_flags, vma->vm_ops, &new_vma); + int ret = mm_create_vma(new_mms, vma->vm_start + i * PAGE_2M_SIZE, PAGE_2M_SIZE, vma->vm_flags, + vma->vm_ops, &new_vma); // 防止内存泄露 if (unlikely(ret == -EEXIST)) free_pages(Phy_to_2M_Page(pa), 1); else mm_map_vma(new_vma, pa, 0, PAGE_2M_SIZE); - memcpy((void *)phys_2_virt(pa), (void *)(vma->vm_start + i * PAGE_2M_SIZE), (vma_size >= PAGE_2M_SIZE) ? PAGE_2M_SIZE : vma_size); + memcpy((void *)phys_2_virt(pa), (void *)(vma->vm_start + i * PAGE_2M_SIZE), + (vma_size >= PAGE_2M_SIZE) ? PAGE_2M_SIZE : vma_size); vma_size -= PAGE_2M_SIZE; } } @@ -1091,7 +1100,8 @@ static int process_rewrite_rbp(struct pt_regs *new_regs, struct process_control_ * @param pcb 新的进程的pcb * @return uint64_t */ -uint64_t process_copy_thread(uint64_t clone_flags, struct process_control_block *pcb, uint64_t stack_start, uint64_t stack_size, struct pt_regs *current_regs) +uint64_t process_copy_thread(uint64_t clone_flags, struct process_control_block *pcb, uint64_t stack_start, + uint64_t stack_size, struct pt_regs *current_regs) { // 将线程结构体放置在pcb后方 struct thread_struct *thd = (struct thread_struct *)(pcb + 1); @@ -1122,7 +1132,8 @@ uint64_t process_copy_thread(uint64_t clone_flags, struct process_control_block // 设置子进程的返回值为0 child_regs->rax = 0; if (pcb->flags & PF_KFORK) - thd->rbp = (uint64_t)(child_regs + 1); // 设置新的内核线程开始执行时的rbp(也就是进入ret_from_system_call时的rbp) + thd->rbp = + (uint64_t)(child_regs + 1); // 设置新的内核线程开始执行时的rbp(也就是进入ret_from_system_call时的rbp) else thd->rbp = (uint64_t)pcb + STACK_SIZE;