环形缓冲块 ringblock
环形块状缓冲区简称为:rbb。与传统的环形缓冲区不同的是,rbb 是一个由很多不定长度的块组成的环形缓冲区,而传统的环形缓冲区是由很多个单字节的 char 组成。rbb 支持 零字节拷贝 。所以 rbb 非常适合用于生产者顺序 put 数据块,消费者顺序 get 数据块的场景,例如:DMA 传输,通信帧的接收与发送等等
ringblk: 是由 多个不同长度 的 block 组成的,ringbuff : 是由单字节的数据组成的。ringblk 每一个 block 有多少个字节可以由用户自己设定。
ringblk 支持零字节拷贝(不需要额外的 memcpy 操作)。所以 rbb 非常适合用于生产者顺序 put 数据块,消费者顺序 get 数据块的场景,例如:DMA 传输,通信帧的接收与发送等等。
初始化
- 初始化块链表和释放链表
- 对每一个块链表进行初始化,并插入到释放链表中
PUT & GET 块
1 2 3
| block->status = RT_RBB_BLK_PUT;
|
- 判断块链表为空,则返回NULL
- 遍历链表,找到具有
RT_RBB_BLK_PUT
状态的块,设置状态为 RT_RBB_BLK_GET
,返回块指针
块释放
- 从块链表总移除块,并插入到释放链表中
rt_rbb_blk_queue_get
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
|
for (; node; node = tmp, tmp = rt_slist_next(node))
{
if (!last_block)
{
last_block = rt_slist_entry(node, struct rt_rbb_blk, list);
if (last_block->status == RT_RBB_BLK_PUT)
{
blk_queue->blocks = last_block;
blk_queue->blk_num = 0;
}
else
{
last_block = RT_NULL;
continue;
}
}
else
{
block = rt_slist_entry(node, struct rt_rbb_blk, list);
if (block->status != RT_RBB_BLK_PUT ||
last_block->buf > block->buf ||
data_total_size + block->size > queue_data_len)
{
break;
}
last_block = block;
}
data_total_size += last_block->size;
last_block->status = RT_RBB_BLK_GET;
blk_queue->blk_num++;
}
|
rt_rbb_blk_alloc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
| rt_rbb_blk_trt_rbb_blk_alloc(rt_rbb_trbb, rt_size_tblk_size)
{
new_rbb = find_empty_blk_in_set(rbb);
if (rt_slist_len(&rbb->blk_list) < rbb->blk_max_num && new_rbb)
{
if (rt_slist_len(&rbb->blk_list) > 0)
{
head = rt_slist_first_entry(&rbb->blk_list, struct rt_rbb_blk, list);
tail = rt_slist_tail_entry(&rbb->blk_list, struct rt_rbb_blk, list);
if (head->buf <= tail->buf)
{
empty1 = (rbb->buf + rbb->buf_size) - (tail->buf + tail->size);
empty2 = head->buf - rbb->buf;
if (empty1 >= blk_size)
{
rt_slist_append(&rbb->blk_list, &new_rbb->list);
new_rbb->status = RT_RBB_BLK_INITED;
new_rbb->buf = tail->buf + tail->size;
new_rbb->size = blk_size;
}
elseif (empty2 >= blk_size)
{
rt_slist_append(&rbb->blk_list, &new_rbb->list);
new_rbb->status = RT_RBB_BLK_INITED;
new_rbb->buf = rbb->buf;
new_rbb->size = blk_size;
}
else
{
new_rbb = NULL;
}
}
else
{
empty1 = head->buf - (tail->buf + tail->size);
if (empty1 >= blk_size)
{
rt_slist_append(&rbb->blk_list, &new_rbb->list);
new_rbb->status = RT_RBB_BLK_INITED;
new_rbb->buf = tail->buf + tail->size;
new_rbb->size = blk_size;
}
else
{
new_rbb = NULL;
}
}
}
else
{
rt_slist_append(&rbb->blk_list, &new_rbb->list);
new_rbb->status = RT_RBB_BLK_INITED;
new_rbb->buf = rbb->buf;
new_rbb->size = blk_size;
}
}
else
{
new_rbb = NULL;
}
return new_rbb;
}
|