Browse Source

暂时解决idr不能跑的问题(目前只能在o1下运行,o0存在栈损坏错误)

longjin 2 years ago
parent
commit
a274d5a01d
3 changed files with 85 additions and 60 deletions
  1. 1 1
      docs/kernel/core_api/data_structures.md
  2. 67 41
      kernel/ktest/test-idr.c
  3. 17 18
      kernel/lib/idr.c

+ 1 - 1
docs/kernel/core_api/data_structures.md

@@ -259,7 +259,7 @@
 
    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定义于`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)`

+ 67 - 41
kernel/ktest/test-idr.c

@@ -103,7 +103,7 @@ static long ktest_idr_case1(uint64_t arg0, uint64_t arg1)
         assert(idr_find(&k_idr, a[i]) == NULL);
     }
 
-    for (int i = 0; i < 128; i++) 
+    for (int i = 0; i < 128; i++)
     {
         assert(idr_count(&k_idr, i) == 0);
     }
@@ -115,7 +115,7 @@ static long ktest_idr_case1(uint64_t arg0, uint64_t arg1)
         assert(a[i] == i);
     }
 
-    for (int i = 0; i < 128; i++) 
+    for (int i = 0; i < 128; i++)
     {
         assert(idr_count(&k_idr, i));
     }
@@ -194,7 +194,7 @@ static long ktest_idr_case2(uint64_t arg0, uint64_t arg1)
     // const int N = 1048576;
     const int M = 2e5;
 
-    int tmp=0;
+    int tmp = 0;
     for (int i = 0; i < N; i++)
     {
         barrier();
@@ -213,7 +213,7 @@ static long ktest_idr_case2(uint64_t arg0, uint64_t arg1)
         assert(idr_count(&k_idr, i));
         barrier();
     }
-// kdebug("111111");
+    // kdebug("111111");
     // 正向: M 个ID
     for (int i = 0; i < M; i++)
     {
@@ -233,7 +233,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("3333333");
+    // kdebug("3333333");
     // 重新插入数据
     for (int i = 0; i < N; i++)
     {
@@ -245,19 +245,19 @@ static long ktest_idr_case2(uint64_t arg0, uint64_t arg1)
         assert(ptr != NULL);
         assert(*ptr == i);
     }
-// kdebug("4444444444");
+    // kdebug("4444444444");
     assert(k_idr.top != NULL);
 
     for (int i = 0; i < M; i++)
     {
         assert(idr_replace(&k_idr, NULL, i) == 0);
     }
-// kdebug("555555555555555555");
+    // kdebug("555555555555555555");
     // 销毁
     idr_destroy(&k_idr);
     assert(k_idr.id_free_cnt == 0);
     assert(k_idr.free_list == NULL);
-// kdebug("666666666666");
+    // kdebug("666666666666");
     return 0;
 }
 
@@ -355,19 +355,19 @@ static long ktest_idr_case4(uint64_t arg0, uint64_t arg1)
     DECLARE_IDR(k_idr);
     idr_init(&k_idr);
 
-    const int N =91173;
-    int tmp;
+    const int N = 91173;
+    static uint32_t tmp;
 
     for (int i = 1; i <= 20; i++)
     {
-        int M = N / i, T = M / 3, O = 2 * T;
+        int M = N / i, T = M / 3, b = 2 * T;
         for (int j = 0; j < M; j++)
         {
             assert(idr_alloc(&k_idr, &tmp, &tmp) == 0);
             assert(tmp == j);
         }
 
-        for (int j = O; j >= T; j--)
+        for (int j = b; j >= T; j--)
         {
             int *ptr = idr_find(&k_idr, j);
             assert(ptr != NULL);
@@ -375,7 +375,7 @@ static long ktest_idr_case4(uint64_t arg0, uint64_t arg1)
             idr_remove(&k_idr, j);
         }
 
-        for (int j = O + 1; j < M; j++)
+        for (int j = b + 1; j < M; j++)
         {
             int *ptr = idr_find(&k_idr, j);
             assert(ptr != NULL);
@@ -427,7 +427,7 @@ static long ktest_idr_case5(uint64_t arg0, uint64_t arg1)
     for (int i = 0; i < N; i++)
     {
         int *ptr;
-        int flags = idr_replace_get_old(&k_idr, &a[(i + 1) % N], i, (void*)&ptr);
+        int flags = idr_replace_get_old(&k_idr, &a[(i + 1) % N], i, (void *)&ptr);
         assert(flags == 0); // 0 是成功
         assert(ptr != NULL);
         assert(*ptr == i);
@@ -481,62 +481,88 @@ static long ktest_idr_case6(uint64_t arg0, uint64_t arg1)
 
     for (int i = 0; i < N; i++)
     {
-        int p_id;io_sfence();
-        assert(ida_alloc(&k_ida, &p_id) == 0);io_sfence();
-        assert(p_id == i);io_sfence();
+        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);io_sfence();
+        assert(ida_count(&k_ida, i) == 1);
+        io_sfence();
     }
 
     for (int i = N - 1; i >= 0; i--)
     {
-        ida_remove(&k_ida, i);io_sfence();
-        assert(ida_count(&k_ida, i) == 0);io_sfence();
+        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;io_sfence();
-        assert(ida_alloc(&k_ida, &p_id) == 0);io_sfence();
-        assert(p_id == i);io_sfence();
+        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);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();
+    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;io_sfence();
-        assert(ida_alloc(&k_ida, &p_id) == 0);io_sfence();
-        assert(p_id == i);io_sfence();
+        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);io_sfence();
-        assert(ida_count(&k_ida, i) == 0);io_sfence();
+        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);io_sfence();
-        assert(ida_count(&k_ida, i) == 0);io_sfence();
+        ida_remove(&k_ida, i);
+        io_sfence();
+        assert(ida_count(&k_ida, i) == 0);
+        io_sfence();
     }
 
-    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();
+    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;
 }
@@ -551,7 +577,7 @@ static ktest_case_table kt_idr_func_table[] = {
     ktest_idr_case6,
 };
 
-int ktest_test_idr(void* arg)
+int ktest_test_idr(void *arg)
 {
     kTEST("Testing idr...");
     unsigned int sz = sizeof(kt_idr_func_table) / sizeof(ktest_case_table);

+ 17 - 18
kernel/lib/idr.c

@@ -1,7 +1,5 @@
 #include <common/idr.h>
 #include <mm/slab.h>
-#pragma GCC push_options
-#pragma GCC optimize("O0")
 
 /**
  * @brief 更换两个idr_layer指针
@@ -222,7 +220,7 @@ static __always_inline void __idr_mark_full(struct idr *idp, int id, struct idr_
     }
 
     // 处理叶子节点的full/bitmap标记
-    int layer_id = __id & IDR_MASK;
+    int64_t layer_id = __id & IDR_MASK;
     if (mark == 2)
         stk[0]->full |= (1ull << layer_id);
     if (mark >= 1)
@@ -270,7 +268,7 @@ static __always_inline int __idr_get_path(struct idr *idp, int id, struct idr_la
     while (layer >= 0)
     {
         stk[layer] = cur_layer;
-        int layer_id = (__id >> (layer * IDR_BITS)) & IDR_MASK;
+        int64_t layer_id = (__id >> (layer * IDR_BITS)) & IDR_MASK;
 
         if (unlikely(((cur_layer->bitmap >> layer_id) & 1) == 0))
         {
@@ -303,7 +301,7 @@ static __always_inline void __idr_erase_full(struct idr *idp, int id, struct idr
     }
 
     // 处理叶子节点的full/bitmap标记
-    int layer_id = __id & IDR_MASK;
+    int64_t layer_id = __id & IDR_MASK;
     if (mark == 0) // 叶子的某个插槽为空
     {
         stk[0]->ary[layer_id] = NULL;
@@ -523,18 +521,24 @@ void *idr_find(struct idr *idp, int id)
     int64_t __id = (int64_t)id;
     if (unlikely(idp->top == NULL || __id < 0))
     {
-        kwarn("idr-find: 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
+    barrier();
     // 如果查询的ID的bit数量比layer*IDR_BITS还大, 直接返回NULL
     if ((__id >> ((layer + 1) * IDR_BITS)) > 0)
         return NULL;
-    while (layer >= 0 && cur_layer)
+    barrier();
+    barrier();
+    int64_t layer_id = 0;
+    while (layer >= 0 && cur_layer != NULL)
     {
-        int layer_id = (__id >> (IDR_BITS * layer)) & IDR_MASK;
+        barrier();
+        layer_id = (__id >> (IDR_BITS * layer)) & IDR_MASK;
+        barrier();
         cur_layer = cur_layer->ary[layer_id];
         --layer;
     }
@@ -606,10 +610,10 @@ void *idr_find_next_getid(struct idr *idp, int64_t start_id, int *nextid)
         unsigned long t_bitmap = (cur_layer->bitmap >> pos_i[layer]);
         if (t_bitmap) // 进一步递归到儿子下面去
         {
-            int layer_id = __lowbit_id(t_bitmap) + pos_i[layer];
+            int64_t layer_id = __lowbit_id(t_bitmap) + pos_i[layer];
 
             // 特别情况
-            if ((cur_state == false) && layer_id > pos_i[layer] > 0)
+            if ((cur_state == false) && (layer_id > pos_i[layer] > 0))
                 cur_state = true;
 
             pos_i[layer] = layer_id;
@@ -685,7 +689,7 @@ int idr_replace_get_old(struct idr *idp, void *ptr, int id, void **old_ptr)
 
     while (layer > 0)
     {
-        int layer_id = (__id >> (layer * IDR_BITS)) & IDR_MASK;
+        int64_t layer_id = (__id >> (layer * IDR_BITS)) & IDR_MASK;
 
         if (unlikely(NULL == cur_layer->ary[layer_id]))
             return -ENOMEM;
@@ -735,8 +739,6 @@ bool idr_empty(struct idr *idp)
 
     return false;
 }
-#pragma GCC push_options
-#pragma GCC optimize("O0")
 
 static bool __idr_cnt_pd(struct idr_layer *cur_layer, int layer_id)
 {
@@ -757,7 +759,7 @@ static bool __idr_cnt(int layer, int id, struct idr_layer *cur_layer)
     {
         barrier();
 
-        int layer_id = (__id >> (layer * IDR_BITS)) & IDR_MASK;
+        int64_t layer_id = (__id >> (layer * IDR_BITS)) & IDR_MASK;
 
         barrier();
 
@@ -774,7 +776,6 @@ static bool __idr_cnt(int layer, int id, struct idr_layer *cur_layer)
     }
     return true;
 }
-#pragma GCC pop_options
 
 /**
  * @brief 这个函数是可以用于判断一个ID是否已经被分配的。
@@ -934,7 +935,7 @@ int ida_alloc(struct ida *ida_p, int *p_id)
     if (unlikely(idr_id < 0))
         return idr_id;
 
-    int layer_id = idr_id & IDR_MASK;
+    int64_t layer_id = idr_id & IDR_MASK;
 
     if (NULL == stk[0]->ary[layer_id])
         stk[0]->ary[layer_id] = __get_ida_bitmap(ida_p, 0);
@@ -1051,5 +1052,3 @@ bool ida_empty(struct ida *ida_p)
 
     return false;
 }
-
-#pragma GCC pop_options