Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MAY BUG @ kernel/core/tos_ring_queue.c #304

Open
wants to merge 2 commits into
base: ver2.4.5
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions kernel/core/tos_binary_heap.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,20 @@ __STATIC__ void bin_heap_do_percolate_up(k_bin_heap_t *bin_heap, uint16_t hole,
void *hole_item, *parent_item;

top = 0u;
parent = BIN_HEAP_PARENT(hole);
parent = BIN_HEAP_PARENT(hole); // hole = 0 时,parent -> 0xffff
cmp = bin_heap->cmp;
item_size = bin_heap->item_size;

// parent = 0xffff 时非法内存访问(嵌入式也许不会出现异常)
hole_item = BIN_HEAP_THE_ITEM(bin_heap, hole);
parent_item = BIN_HEAP_THE_ITEM(bin_heap, parent);

while (hole > top && cmp(item_backup, parent_item)) {
memcpy(hole_item, parent_item, item_size);
hole = parent;
parent = BIN_HEAP_PARENT(hole);

// 非法内存访问
hole_item = BIN_HEAP_THE_ITEM(bin_heap, hole);
parent_item = BIN_HEAP_THE_ITEM(bin_heap, parent);
}
Expand Down Expand Up @@ -86,6 +89,8 @@ __STATIC__ void bin_heap_percolate_down(k_bin_heap_t *bin_heap)
item_size = bin_heap->item_size;

hole_item = BIN_HEAP_THE_ITEM(bin_heap, hole);

// 非法内存访问,当此时 the_child >= bin_heap->total
rchild_item = BIN_HEAP_THE_ITEM(bin_heap, rchild);
lchild_item = BIN_HEAP_THE_ITEM(bin_heap, lchild);

Expand All @@ -106,11 +111,18 @@ __STATIC__ void bin_heap_percolate_down(k_bin_heap_t *bin_heap)
lchild_item = BIN_HEAP_THE_ITEM(bin_heap, lchild);
}

// bin_heap->total 在 tos_bin_heap_pop 中通过 bin_heap_item_decrease 先减了 1
// 假如本来有 3 个元素,现在 pop 一下就会变成 2 个,而 the_child 也是 2
// 这里直接将左节点的值赋值给父节点不正确,对于小根堆,如果右节点比左节点小,
// 那么小根堆将出现父节点大于子结点的情况
// 而左节点会在 bin_heap_do_percolate_up 中被替换成 BIN_HEAP_LAST_ITEM(bin_heap),
// 也就是被替换成右节点
if (the_child == bin_heap->total) {
memcpy(hole_item, lchild_item, item_size);
hole = lchild;
hole = lchild; // hole 指向左节点
hole_item = BIN_HEAP_THE_ITEM(bin_heap, hole);
}

bin_heap_do_percolate_up(bin_heap, hole, BIN_HEAP_LAST_ITEM(bin_heap));
}

Expand Down
3 changes: 3 additions & 0 deletions kernel/core/tos_ring_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,9 @@ __API__ k_err_t tos_ring_q_dequeue(k_ring_q_t *ring_q, void *item, size_t *item_

TOS_CPU_INT_DISABLE();

// tos_ring_q_is_empty 内部使用了 TOS_CPU_INT_ENABLE()
// 如果中断的开闭不是递归锁将导致同步问题
// 其他地方应该也有类似的问题
if (tos_ring_q_is_empty(ring_q)) {
TOS_CPU_INT_ENABLE();
return K_ERR_RING_Q_EMPTY;
Expand Down